﻿#define _CRT_SECURE_NO_WARNINGS 1

#include<iostream>
using namespace std;

#include <queue>
#include <vector>

//https://leetcode.cn/problems/kth-largest-element-in-an-array/submissions/
// 215. 数组中的第K个最大元素
//给定整数数组 nums 和整数 k，请返回数组中第 k 个最大的元素。
//
//请注意，你需要找的是数组排序后的第 k 个最大的元素，而不是第 k 个不同的元素。
//
//你必须设计并实现时间复杂度为 O(n) 的算法解决此问题。

//示例 1:
//
//输入: [3, 2, 1, 5, 6, 4] , k = 2
//输出 : 5


//class Solution {
//public:
//    int findKthLargest(vector<int>& nums, int k)
//    {
//        //用堆来实现
//        //升序建大堆
//        //迭代器区间初始化 直接建大堆， 默认不给仿函数是大堆
//        priority_queue<int> pq(nums.begin(), nums.end());
//        while (--k)
//        {
//            pq.pop();
//        }
//        return pq.top();
//    }
//};





//https://leetcode.cn/problems/move-zeroes/description/
//283. 移动零
//给定一个数组 nums，编写一个函数将所有 0 移动到数组的末尾，同时保持非零元素的相对顺序。
//
//请注意 ，必须在不复制数组的情况下原地对数组进行操作。
//
//示例 1:
//
//输入: nums = [0, 1, 0, 3, 12]
//输出 : [1, 3, 12, 0, 0]

//class Solution {
//public:
//    void moveZeroes(vector<int>& nums) {
//        int dest = 0;
//        for (int cur = 0; cur < nums.size(); ++cur)
//        {
//            if (nums[cur] != 0)
//            {
//                swap(nums[cur], nums[dest]);
//                ++dest;
//            }
//        }
//    }
//
//    // 一些优化后更加简短的语句
//    //void moveZeroes(vector<int>& nums) {
//    //    for (int cur = 0, dest = 0; cur < nums.size(); ++cur)
//    //    {
//    //        if (nums[cur] != 0)
//    //            swap(nums[cur], nums[dest++]);
//    //    }
//    //}
//
//};





//https://leetcode.cn/problems/duplicate-zeros/description/
//1089. 复写零
//
//给你一个长度固定的整数数组 arr ，请你将该数组中出现的每个零都复写一遍，并将其余的元素向右平移。
//注意：请不要在超过该数组长度的位置写入元素。请对输入的数组 就地 进行上述修改，不要从函数返回任何东西。
//
//输入：arr = [1, 0, 2, 3, 0, 4, 5, 0]
//输出：[1, 0, 0, 2, 3, 0, 0, 4]
//解释：调用函数后，输入的数组将被修改为：[1, 0, 0, 2, 3, 0, 0, 4]

//class Solution
//{
//public:
//    void duplicateZeros(vector<int>& arr)
//    {
//        第一步先用双指针找出最后一个需要复写的值的位置
//        关键是要这个 dest 为-1
//        定义一个 cur 是当前的位置，dest 是需要放元素的下标的位置
//        int cur = 0, dest = -1, n = arr.size();
//        while (cur < n)
//        {
//            if (arr[cur] != 0)
//                ++dest;
//            else
//                dest += 2;
//            if (dest >= n - 1)
//                break;
//            ++cur;
//        }
//         出来后进行判断是否有越界 复写0会出问题
//        if (dest == n)
//        {
//            arr[n - 1] = 0;
//            dest -= 2;
//            --cur;
//        }
//        从后往前完成复写操作
//        while (cur >= 0)
//        {
//            if (arr[cur] != 0)
//            {
//                arr[dest--] = arr[cur--];
//            }
//            else
//            {
//                arr[dest--] = arr[cur];
//                arr[dest--] = arr[cur];
//                --cur;
//            }
//        }
//    }

    // void duplicateZeros(vector<int>& arr) 
    // {
    //     //第一步先用双指针找出最后一个需要复写的值的位置
    //     //关键是要这个 dest 为-1 不然程序会很难写
    //     //如果 dest 是 0 的话写法会有一些奇怪
    //     int cur = 0, dest = 0, n =arr.size();
    //     while(cur < n)
    //     {
    //         if(arr[cur] != 0)
    //         {
    //             ++dest;
    //         }
    //         else
    //         {
    //             dest += 2;
    //         }
    //         if(dest >= n)
    //         {
    //             break;
    //         }
    //         ++cur;
    //     }
    //     if(dest == n)
    //     {
    //         --dest;
    //     }
    //     else if(dest == n+1)
    //     {
    //         arr[n-1] = 0;
    //         dest -= 3;
    //         --cur;
    //     }
    //     //从后往前完成复写操作
    //     while(cur >= 0)
    //     {
    //         if(arr[cur] != 0)
    //         {
    //             arr[dest--] = arr[cur--];
    //         }
    //         else
    //         {
    //             arr[dest--] = arr[cur];
    //             arr[dest--] = arr[cur];
    //             --cur;
    //         }
    //     }
    // }

//};





//https://leetcode.cn/problems/happy-number/
//202. 快乐数
//编写一个算法来判断一个数 n 是不是快乐数。
//「快乐数」 定义为：
//
//对于一个正整数，每一次将该数替换为它每个位置上的数字的平方和。
//然后重复这个过程直到这个数变为 1，也可能是 无限循环 但始终变不到 1。
//如果这个过程 结果为 1，那么这个数就是快乐数。
//
//如果 n 是 快乐数 就返回 true ；不是，则返回 false 。


//class Solution {
//public:
//    int _ishappy(int n)
//    {
//        int sum = 0;
//        while (n)
//        {
//            int tmp = n % 10;
//            sum += pow(tmp, 2);
//            n /= 10;
//        }
//        return sum;
//    }
//    //第二种方法 看成类似于链表带环 来做 慢指针一次  快指针两次
//    bool isHappy(int n)
//    {
//        int slow, fast;
//        //slow = fast = n;
//        slow = n; fast = _ishappy(n);
//
//        //或者while(1) 在里面判断 上面改一下
//        while (slow != fast)
//        {
//            fast = _ishappy(_ishappy(fast));
//            slow = _ishappy(slow);
//        }
//        return fast == 1;
//    }

    // bool isHappy(int n) 
    // {
    //     //试试用 set 可以做
    //     //通过了 解题的一种思路
    //     unordered_set<int> s;
    //     int num = n;
    //     // pair<unordered_set<int>::iterator, int> sret = s.insert(num);
    //     auto sret = s.insert(num);

    //     //鸽巢原理 一定能 break 的
    //     // while(sret.second == false)
    //     while(1)
    //     {
    //         num = _ishappy(num);
    //         sret = s.insert(num);
    //         if(sret.second == false)
    //             break;         
    //     }
    //         return num == 1;
    // }
//};



//https://leetcode.cn/problems/container-with-most-water/
//11. 盛最多水的容器
//给定一个长度为 n 的整数数组 height 。有 n 条垂线，第 i 条线的两个端点是(i, 0) 和(i, height[i]) 。
//找出其中的两条线，使得它们与 x 轴共同构成的容器可以容纳最多的水。
//返回容器可以储存的最大水量。
//说明：你不能倾斜容器。
//输入：[1, 8, 6, 2, 5, 4, 8, 3, 7]
//输出：49
//解释：图中垂直线代表输入数组[1, 8, 6, 2, 5, 4, 8, 3, 7]。在此情况下，容器能够容纳水（表示为蓝色部分）的最大值为 49。
//class Solution {
//public:
//    int maxArea(vector<int>& height)
//    {
//        // 双指针left 和 right
//        // 而不是暴力求解
//        // 有两个变量能控制水重量 一个是高度，一个是宽度
//        // 本质也是先从宽度入手，最长宽的时候 然后宽一直--
//        int left = 0, right = height.size() - 1;
//        int max = 0;
//        while (left < right)
//        {
//            int width = right - left;
//            int high = min(height[right], height[left]);
//            int val = width * high;
//            if (val > max)
//                max = val;
//            if (high == height[left])
//                ++left;
//            else
//                --right;
//        }
//        return max;
//    }
//};



//https://leetcode.cn/problems/he-wei-sde-liang-ge-shu-zi-lcof/description/
//LCR 179. 查找总价格为目标值的两个商品
//购物车内的商品价格按照升序记录于数组 price。请在购物车中找到两个商品的价格总和刚好是 target。若存在多种情况，返回任一结果即可。

//输入：price = [3, 9, 12, 15], target = 18
//输出：[3, 15] 或者[15, 3]

//class Solution {
//public:
//    vector<int> twoSum(vector<int>& price, int target)
//    {
//        int left = 0, right = price.size() - 1;
//        vector<int> retv;
//        while (left < right)
//        {
//            if (price[left] + price[right] > target)
//            {
//                //说明 最小值 + 最大值都已经大于 target 了 left++ 无意义
//                --right;
//            }
//            else if (price[left] + price[right] < target)
//            {
//                //同理 应该 ++left
//                ++left;
//            }
//            else
//            {
//                break;
//            }
//        }
//        //说明找到了目标值
//        retv.push_back(price[left]);
//        retv.push_back(price[right]);
//        return retv;
//    }
//
//    //或者用这种写法 {} 返回
//    vector<int> twoSum(vector<int>& price, int target)
//    {
//        int left = 0, right = price.size() - 1;
//        while (left < right)
//        {
//            int sum = price[left] + price[right];
//            if (sum > target)
//                --right;
//            else if (sum < target)
//                ++left;
//            else //说明相等
//                break;
//        }
//        return { price[left], price[right] };
//    }
//
//};


//https://leetcode.cn/problems/valid-triangle-number/description/
//611. 有效三角形的个数

//class Solution {
//public:
//    int triangleNumber(vector<int>& nums)
//    {
//        sort(nums.begin(), nums.end());
//        int count = 0;
//        int end = nums.size() - 1;
//        //先固定一个最大值
//        for (int i = end; i >= 2; --i)
//        {
//            int left = 0, right = i - 1;
//            while (left < right)
//            {
//                //如果 大于这个固定的最大值了 说明left往右到right为止都是可以的
//                if (nums[left] + nums[right] > nums[i])
//                {
//                    //同时 这个right的情况已经考虑完了，--
//                    count += right - left;
//                    --right;
//                }
//                else
//                {
//                    ++left;
//                }
//            }
//        }
//        return count;
//    }
//
//    //暴力求解，三角形条件 两条最短边相加大于第三条边就是三角形
//    //超时
//    // int triangleNumber(vector<int>& nums) 
//    // {
//    //     sort(nums.begin(), nums.end());
//    //     int count = 0; 
//    //     int end = nums.size();
//
//    //     for(int i = 0; i < end; ++i)
//    //     {
//    //         for(int j = i+1; j < end ; ++j)
//    //         {
//    //             for(int k = j+1; k < end; ++k)
//    //             {
//    //                 if(nums[i]+nums[j] > nums[k])
//    //                     ++count;
//    //                 else
//    //                     break;
//    //             }
//    //         }
//    //     }
//    //     return  count;
//
//// }
//};




//https://www.nowcoder.com/practice/fe298c55694f4ed39e256170ff2c205f?tpId=37&tqId=21245&ru=/exam/oj
//HJ22 汽水瓶
//描述
//某商店规定：三个空汽水瓶可以换一瓶汽水，允许向老板借空汽水瓶（但是必须要归还）。
//小张手上有n个空汽水瓶，她想知道自己最多可以喝到多少瓶汽水。
//数据范围：输入的正整数满足 1≤n≤100 1≤n≤100
//
//注意：本题存在多组输入。输入的 0 表示输入结束，并不用输出结果。
//输入描述：
//输入文件最多包含 10 组测试数据，每个数据占一行，仅包含一个正整数 n（ 1 <= n <= 100 ），表示小张手上的空汽水瓶数。n = 0 表示输入结束，你的程序不应当处理这一行。
//输出描述：
//对于每组测试数据，输出一行，表示最多可以喝的汽水瓶数。如果一瓶也喝不到，输出0。
//输入：
//3
//10
//81
//0
//输出：
//1
//5
//40


//int main()
//{
//    int empty_bottle = 0;
//    while (cin >> empty_bottle)
//    {
//        if (empty_bottle == 0)
//            break;
//        int drink = 0;
//        int sum = 0;
//        while (empty_bottle != 1)
//        {
//            drink = empty_bottle / 3;
//            sum += drink;
//            empty_bottle = empty_bottle % 3 + drink;
//            if (empty_bottle == 2)
//            {
//                ++sum;
//                break;
//            }
//        }
//        cout << sum << endl;
//    }
//}


//https://leetcode.cn/problems/1fGaJU/description/
//LCR 007. 三数之和
//给定一个包含 n 个整数的数组 nums，判断 nums 中是否存在三个元素 a ，b ，c ，使得 a + b + c = 0 ？请找出所有和为 0 且 不重复 的三元组。
//示例 1：
//输入：nums = [-1, 0, 1, 2, -1, -4]
//输出： [[-1, -1, 2], [-1, 0, 1]]
class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums)
    {
        vector<vector<int>> retvv;
        //默认升序
        sort(nums.begin(), nums.end());
        //先固定一个数
        for (int i = 0; i < nums.size(); ) //这里判断条件就不要了
        {
            int target = 0 - nums[i];
            int left = i + 1, right = nums.size() - 1;
            while (left < right)
            {
                int sum = nums[left] + nums[right];
                if (sum > target)
                {
                    --right;
                }
                else if (sum < target)
                {
                    ++left;
                }
                else
                {
                    retvv.push_back({ nums[i], nums[left], nums[right] });
                    --right;
                    ++left;
                    while (right >= 0 && nums[right] == nums[right + 1])
                        --right;
                    while (left <= nums.size() - 1 && nums[left] == nums[left - 1])
                        ++left;
                }
            }
            i++;
            while (i < nums.size() && nums[i] == nums[i - 1])
                ++i;
        }
        return retvv;
    }
};





//https://www.nowcoder.com/practice/5a0a2c7e431e4fbbbb1ff32ac6e8dfa0?tpId=122&tqId=33670&ru=/exam/oj
// 洗牌
//洗牌在生活中十分常见，现在需要写一个程序模拟洗牌的过程。 现在需要洗2n张牌，从上到下依次是第1张，第2张，第3张一直到第2n张。首先，我们把这2n张牌分成两堆，左手拿着第1张到第n张（上半堆），右手拿着第n+1张到第2n张（下半堆）。接着就开始洗牌的过程，先放下右手的最后一张牌，再放下左手的最后一张牌，接着放下右手的倒数第二张牌，再放下左手的倒数第二张牌，直到最后放下左手的第一张牌。接着把牌合并起来就可以了。 例如有6张牌，最开始牌的序列是1,2,3,4,5,6。首先分成两组，左手拿着1,2,3；右手拿着4,5,6。在洗牌过程中按顺序放下了6,3,5,2,4,1。把这六张牌再次合成一组牌之后，我们按照从上往下的顺序看这组牌，就变成了序列1,4,2,5,3,6。 现在给出一个原始牌组，请输出这副牌洗牌k次之后从上往下的序列。
//输入描述:
//第一行一个数T(T ≤ 100)，表示数据组数。对于每组数据，第一行两个数n,k(1 ≤ n,k ≤ 100)，接下来有2n行个数a1,a2,...,a2n(1 ≤ ai ≤ 1000000000)。表示原始牌组从上到下的序列。
//输出描述:
//对于每组数据，输出一行，最终的序列。数字之间用空格隔开，不要在行末输出多余的空格。
//示例1
//输入
//3
//3 1
//1
//2
//3
//4
//5
//6
//3 2
//1
//2
//3
//4
//5
//6
//2 2
//1
//1
//1
//1
//输出
//1 4 2 5 3 6
//1 5 4 3 2 6
//1 1 1 1
#include <iostream>
#include <vector>
using namespace std;

//int main() {
//    int T, k, n, number;
//
//    while (cin >> T)
//    {
//        while (T--)
//        {
//            while (cin >> n >> k)
//            {
//                vector<int> left, right;
//                for (int i = 0; i < 2 * n; ++i)
//                {
//                    cin >> number;
//                    if (i < n)
//                        left.push_back(number);
//                    else
//                        right.push_back(number);
//                }
//
//                vector<int> wash_card;
//                while (k--)
//                {
//                    //洗牌
//                    if (!wash_card.empty())
//                        wash_card.clear();
//                    for (int i = 0; i < n; ++i)
//                    {
//                        wash_card.push_back(left[i]);
//                        wash_card.push_back(right[i]);
//                    }
//                    //洗完继续分 left right
//                    left.clear(); right.clear();
//                    for (int i = 0; i < 2 * n; ++i)
//                    {
//                        if (i < n)
//                            left.push_back(wash_card[i]);
//                        else
//                            right.push_back(wash_card[i]);
//                    }
//
//                }
//                for (auto e : wash_card)
//                {
//                    cout << e << " ";
//                }
//                cout << endl;
//                break;
//            }
//        }
//    }
//
//}

//https://www.nowcoder.com/practice/fe6c73cb899c4fe1bdd773f8d3b42c3d?tpId=122&tqId=33649&ru=/exam/oj
//WY3 小易的升级之路
//小易经常沉迷于网络游戏.有一次, 他在玩一个打怪升级的游戏, 他的角色的初始能力值为 a.在接下来的一段时间内, 他将会依次遇见n个怪物, 每个怪物的防御力为b1, b2, b3...bn.如果遇到的怪物防御力bi小于等于小易的当前能力值c, 那么他就能轻松打败怪物, 并 且使得自己的能力值增加bi; 如果bi大于c, 那他也能打败怪物, 但他的能力值只能增加bi 与c的最大公约数.那么问题来了, 在一系列的锻炼后, 小易的最终能力值为多少 ?
//输入描述 :
//    对于每组数据, 第一行是两个整数n(1≤n100000)表示怪物的数量和a表示小易的初始能力值.然后输入n行，每行整数, b1, b2...bn(1≤bi≤n)表示每个怪物的防御力
//    输出描述 :
//对于每组数据, 输出一行.每行仅包含一个整数, 表示小易的最终能力值
//输入
//3 50
//50 105 200
//5 20
//30 20 15 40 100
//输出
//110
//205

#include <iostream>
using namespace std;

//最大公约数 greatest common divisor
//int gcd(int a, int b)
//{
//    int small = a, big = b;
//    if (a > b)
//    {
//        small = b;
//        big = a;
//    }
//    for (int i = small; i > 0; --i)
//    {
//        if (big % i == 0 && small % i == 0)
//            return i;
//    }
//    //没找到
//    return 0;
//}
//
//int main()
//{
//    int n, a, b;
//    while (cin >> n >> a)
//    {
//        int final = a;
//        for (int i = 0; i < n; ++i)
//        {
//            cin >> b;
//            if (final >= b)
//                final += b;
//            else
//                final += gcd(final, b);
//        }
//        cout << final << endl;
//    }
//}



//https://www.nowcoder.com/practice/e896d0f82f1246a3aa7b232ce38029d4?tpId=37&tqId=21282&ru=/exam/oj
//HJ59 找出字符串中第一个只出现一次的字符
//找出字符串中第一个只出现一次的字符 数据范围：输入的字符串长度满足
//输入描述 :
//输入一个非空字符串
//输出描述 :
//输出第一个只出现一次的字符，如果不存在输出 - 1
//示例1
//输入
//asdfasdfo
//输出
//o

#include <unordered_map>
//int main()
//{
//    string str;
//    unordered_map<char, int> m;
//    int flag = 1;
//    getline(cin, str);
//    for (auto e : str)
//    {
//        m[e]++;
//    }
//    for (auto e : str)
//    {
//        if (m[e] == 1)
//        {
//            flag = 0;
//            cout << e << endl;
//            break;
//        }
//    }
//    if (flag == 1)
//        cout << -1 << endl;
//
//}





//class Solution {
//public:
//    //   错在了 用 else if  错过了一些判断  还好现在 都对了
//    int minSubArrayLen(int target, vector<int>& nums)
//    {
//        int left, right;
//        left = right = 0;
//        //滑动窗口 双指针  同向走
//        int sum = nums[right];
//        int len = nums.size() + 1;
//        while (right < nums.size())
//        {
//            if (sum < target)
//            {
//                ++right;
//                if (right > nums.size() - 1)
//                    break;
//                sum += nums[right];
//            }
//            if (sum >= target)
//            {
//                len = min(len, right - left + 1);
//                sum -= nums[left];
//                ++left;
//            }
//        }
//        //既然最上面选择了  int len = nums.size();  示例3是不会执行到 else if 的
//        return len == nums.size() + 1 ? 0 : len;
//    }
//
//    // int minSubArrayLen(int target, vector<int>& nums) 
//    // {
//    //     int left, right;
//    //     left = right = 0;
//    //     //滑动窗口 双指针  同向走
//    //     int sum = 0;
//    //     int len = nums.size()+1; //如果全部下标对应值加起来刚好等于 target len 也是等于 nums.size() 所以+1避免一下
//    //     while(right < nums.size())
//    //     {
//    //         sum += nums[right];
//    //         while(sum >= target)
//    //         {
//    //             //达到了满足的条件 记录一下长度
//    //             len = min(len, right - left + 1);
//    //             sum -= nums[left];
//    //             ++left;
//    //         }
//    //         ++right;
//    //     }
//    //     //既然最上面选择了  int len = nums.size()+1;  示例3是不会执行到 else if 的
//    //     return len == nums.size()+1? 0 : len;
//    // }
//};

//int main()
//{
//    Solution s1;
//    vector<int> num = { 2,3,1,2,4,3 };
//    int ret = s1.minSubArrayLen(7, num);
//    cout << ret << endl;
//    return 0;
//}




//https://leetcode.cn/problems/add-two-numbers/submissions/
//2. 两数相加
//给你两个 非空 的链表，表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的，并且每个节点只能存储 一位 数字。
//请你将两个数相加，并以相同形式返回一个表示和的链表。
//你可以假设除了数字 0 之外，这两个数都不会以 0 开头。
//输入：l1 = [2, 4, 3], l2 = [5, 6, 4]
//输出：[7, 0, 8]
//解释：342 + 465 = 807.

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */

//class Solution {
//public:
//    // ListNode* addTwoNumbers(ListNode* l1, ListNode* l2)
//    // {
//    //     ListNode* phead = new ListNode;
//    //     ListNode* cur = phead;
//    //     int carry = 0;
//    //     int ret = 0;
//    //     int num1,num2,sum;
//
//    //     while(l1 && l2)
//    //     {
//    //         num1 = l1->val;
//    //         num2 = l2->val;
//    //         sum = num1 + num2 + carry;
//    //         carry = sum / 10;
//    //         ret = sum % 10;
//
//    //         ListNode* tmp = new ListNode;
//    //         cur->next = tmp;
//    //         tmp->val = ret;
//    //         cur = cur->next;
//
//    //         l1 = l1->next;
//    //         l2 = l2->next;
//    //     }
//    //     while(l1)
//    //     {
//    //         num1 = l1->val;
//    //         sum = num1 + carry;
//    //         carry = sum / 10;
//    //         ret = sum % 10;
//    //         ListNode* tmp = new ListNode;
//    //         cur->next = tmp;
//    //         tmp->val = ret;
//    //         cur = cur->next;   
//
//    //         l1 = l1->next;
//    //     }
//
//    //     while(l2)
//    //     {
//    //         num2 = l2->val;
//    //         sum = num2 + carry;
//    //         carry = sum / 10;
//    //         ret = sum % 10;
//    //         ListNode* tmp = new ListNode;
//    //         cur->next = tmp;
//    //         tmp->val = ret;
//    //         cur = cur->next;   
//
//    //         l2 = l2->next;
//    //     }
//
//    //     if(carry == 1)
//    //     {
//    //         ListNode* tmp = new ListNode;
//    //         cur->next = tmp;
//    //         tmp->val = 1;
//    //         cur = cur->next;
//    //     }
//    //     cur->next = nullptr;
//
//    //     return phead->next;
//    // }
//
//
//    //小优化 哈哈
//    ListNode* addTwoNumbers(ListNode* l1, ListNode* l2)
//    {
//        ListNode* phead = new ListNode;
//        ListNode* cur = phead;
//        int carry = 0;
//        int ret = 0;
//        int num1, num2, sum;
//
//        while (l1 || l2)
//        {
//            if (l1 == nullptr)
//                num1 = 0;
//            else if (l2 == nullptr)
//                num2 = 0;
//
//            num1 = (l1 == nullptr ? 0 : l1->val);
//            num2 = (l2 == nullptr ? 0 : l2->val);
//
//            sum = num1 + num2 + carry;
//            carry = sum / 10;
//            ret = sum % 10;
//
//            ListNode* tmp = new ListNode;
//            cur->next = tmp;
//            tmp->val = ret;
//            cur = cur->next;
//
//            if (l1 != nullptr)
//                l1 = l1->next;
//            if (l2 != nullptr)
//                l2 = l2->next;
//
//        }
//
//        if (carry == 1)
//        {
//            ListNode* tmp = new ListNode;
//            cur->next = tmp;
//            tmp->val = 1;
//            cur = cur->next;
//        }
//        cur->next = nullptr;
//
//        return phead->next;
//    }
//
//
//    // ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) 
//    // {
//    //     long long num1 = 0, num2 = 0;
//    //     vector<int> v;
//    //     while(l1)
//    //     {
//    //         v.push_back(l1->val);            
//    //         l1 = l1->next;
//    //     }
//    //     for(int i = v.size()-1; i >= 0; --i)
//    //     {
//    //         num1 = num1*10 + v[i];
//    //     }
//    //     cout << num1 <<endl;
//
//    //     v.clear();
//    //     while(l2)
//    //     {
//    //         v.push_back(l2->val);    
//    //         l2 = l2->next;
//    //     }
//    //     for(int i = v.size()-1; i >= 0; --i)
//    //     {
//    //         num2 = num2*10 +v[i];
//    //     }
//    //     cout << num2 <<endl;
//
//    //     long long sum = num1 + num2;
//
//    //     cout << sum <<endl;
//    //     ListNode* phead = new ListNode;
//    //     ListNode* cur = phead;
//
//    //     do
//    //     {
//    //         ListNode* tmp = new ListNode;
//    //         tmp->val = sum % 10;
//    //         sum /= 10;
//
//    //         cur->next = tmp;
//    //         cur = cur->next;
//    //     }while(sum);
//
//    //     cur->next = nullptr;
//    //     return phead->next;
//    // }
//};



//https://leetcode.cn/problems/two-sum/description/
//1. 两数之和
//相关企业
//给定一个整数数组 nums 和一个整数目标值 target，请你在该数组中找出 和为目标值 target  的那 两个 整数，并返回它们的数组下标。
//你可以假设每种输入只会对应一个答案。但是，数组中同一个元素在答案里不能重复出现。
//你可以按任意顺序返回答案。
//class Solution {
//public:
//
//     vector<int> twoSum(vector<int>& nums, int target)
//     {
//         unordered_map<int, int> map;
//         //关键是要一一对应， 也可以用迭代器来寻找 first 和 second   key / value
//         for(int i = 0; i< nums.size(); ++i)
//         {
//             auto it = map.find(target - nums[i]);
//             if(it != map.end())
//                 return  {it->second, i};
//             //每次进来都先将数据插入
//             map[nums[i]] = i;
//         }
//         return {};
//     }
//
//    // 错的
//    // vector<int> twoSum(vector<int>& nums, int target) 
//    // {
//    //     int left = 0, right = nums.size()-1;
//    //     sort(nums.begin(), nums.end());
//    //     while(left < right)
//    //     {
//    //         int sum = nums[left] + nums[right];
//    //         if(sum > target)
//    //         {
//    //             --right;
//    //         }
//    //         else if(sum < target)
//    //         {
//    //             ++left;
//    //         }
//    //         else
//    //         {
//    //             break;
//    //         }
//    //     }    
//    //     return {left, right};
//    // }
//};

//int main()
//{
//    Solution s1;
//    vector<int> num = { 2,3,1,2,4,3 };
//    int ret = s1.minSubArrayLen(7, num);
//    cout << ret << endl;
//    return 0;
//}




//18. 四数之和
//给你一个由 n 个整数组成的数组 nums ，和一个目标值 target 。请你找出并返回满足下述全部条件且不重复的四元组[nums[a], nums[b], nums[c], nums[d]] （若两个四元组元素一一对应，则认为两个四元组重复）：
//0 <= a, b, c, d < n
//a、b、c 和 d 互不相同
//nums[a] + nums[b] + nums[c] + nums[d] == target
//
//你可以按 任意顺序 返回答案 。
//示例 1：
//输入：nums = [1, 0, -1, 0, -2, 2], target = 0
//输出： [[-2, -1, 1, 2], [-2, 0, 0, 2], [-1, 0, 0, 1]]
//class Solution {
//public:
//    vector<vector<int>> fourSum(vector<int>& nums, int target)
//    {
//        //先固定一个数
//        int n = nums.size() - 1;
//        vector<vector<int>> retv;
//        sort(nums.begin(), nums.end());
//        for (int i = 0; i < n; )
//        {
//            //然后可以用三数之和的算法来求
//            for (int j = i + 1; j < n; )
//            {
//                int left = j + 1, right = n;
//                long long aim = (long long)target - nums[i] - nums[j];
//                while (left < right)
//                {
//                    int sum = nums[left] + nums[right];
//                    if (sum > aim)
//                        --right;
//                    else if (sum < aim)
//                        ++left;
//                    else
//                    {
//                        //说明相等
//                        retv.push_back({ nums[i], nums[j], nums[left], nums[right] });
//                        left++;
//                        right--;
//                        //去重判断
//                        while (left < n && nums[left] == nums[left - 1]) { ++left; }
//                        while (right > 0 && nums[right] == nums[right + 1]) { --right; }
//                    }
//                }
//                //去重判断
//                ++j;
//                while (j < n && nums[j] == nums[j - 1]) { ++j; }
//            }
//            ++i;
//            while (i < n && nums[i] == nums[i - 1]) { ++i; }
//        }
//        return retv;
//    }
//};




//3. 无重复字符的最长子串
//
//给定一个字符串 s ，请你找出其中不含有重复字符的 最长子串 的长度。
//
//输入: s = "abcabcbb"
//输出 : 3
//解释 : 因为无重复字符的最长子串是 "abc"，所以其长度为 3。
//V1 版本 还能再优化一下写法
class Solution {
public:
    int lengthOfLongestSubstring(string s)
    {
        //map 类型为整形时 的 value 默认是 0
        unordered_map<int, int> hash;
        int left = 0, right = 0;
        int len = 0;
        while (right < s.size())
        {
            auto it = hash.find(s[right]);
            if (it != hash.end() && it->second == 1)
            {
                it->second++;
                while (hash[s[right]] == 2)
                {
                    hash[s[left]]--;
                    ++left;
                }
                ++right;
            }
            else
            {
                hash[s[right]]++;
                len = max(len, right - left + 1);
                right++;
            }
        }

        return len;
    }

    int lengthOfLongestSubstringv2(string s)
    {
        unordered_map<char, int> hash;
        //int hash[128]={0};
        int left = 0, right = 0;
        int len = 0;
        while (right < s.size())
        {
            hash[s[right]]++;
         //   cout << s[right] << " " << hash[s[right]] << endl;
            while (hash[s[right]] > 1)
            {
                cout << "hh";
                hash[s[left++]]--;
            }
            len = max(len, right - left + 1);
            right++;
        }
        return len;
    }
};


int main()
{
    Solution s;
    cout << s.lengthOfLongestSubstringv2("abcabcbb") << endl;;
    return 0;
}



//https://leetcode.cn/problems/max-consecutive-ones-iii/description/
//1004. 最大连续1的个数 III
//给定一个二进制数组 nums 和一个整数 k，如果可以翻转最多 k 个 0 ，则返回 数组中连续 1 的最大个数 。
//
//输入：nums = [0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1], K = 3
//输出：10
//解释：[0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1]
//粗体数字从 0 翻转到 1，最长的子数组长度为 10

class Solution {
public:

    int longestOnes(vector<int>& nums, int k)
    {
        //其实不用想那么复杂，看包含的 0 的个数就可以了
        int len = 0;
        for (int left = 0, right = 0; right < nums.size(); ++right)
        {
            if (nums[right] == 0)
                k--;
            //此时开始出窗口，条件可以优化
            while (k < 0)
            {
                if (nums[left++] == 0)
                    k++;
            }
            len = max(len, right - left + 1);
        }
        return len;
    }


    // int longestOnes(vector<int>& nums, int k) 
    // {
    //     //其实不用想那么复杂，看包含的 0 的个数就可以了
    //     int len = 0;
    //     for(int left = 0, right = 0; right < nums.size(); ++right)
    //     {
    //         if(nums[right] == 0)
    //         {
    //             k--;
    //         }
    //         if(k < 0)
    //         {
    //             while(k != 0)
    //             {
    //                 if(nums[left++] == 0)
    //                 {
    //                     k++;
    //                 }
    //             }
    //         }
    //         len = max(len, right - left + 1);
    //     }
    //     return len;
    // }


    //int longestOnes(vector<int>& nums, int k)
    //{
    //    int left, right;
    //    int len = 0;
    //    left = right = 0;
    //    while (right < nums.size())
    //    {
    //        if (nums[right] == 0)
    //        {
    //            k--;
    //            if (k < 0)
    //            {
    //                //左边要出窗口了
    //                while (k != 0)
    //                {
    //                    if (nums[left] == 0)
    //                        k++;
    //                    left++;
    //                }
    //            }
    //        }
    //        len = max(len, right - left + 1);
    //        right++;
    //    }
    //    return len;
    //}
};





//1658. 将 x 减到 0 的最小操作数
//给你一个整数数组 nums 和一个整数 x 。每一次操作时，你应当移除数组 nums 最左边或最右边的元素，然后从 x 中减去该元素的值。请注意，需要 修改 数组以供接下来的操作使用。
//如果可以将 x 恰好 减到 0 ，返回 最小操作数 ；否则，返回 - 1 。
//示例 1：
//输入：nums = [1, 1, 4, 2, 3], x = 5
//输出：2
//解释：最佳解决方案是移除后两个元素，将 x 减到 0 。
//class Solution {
//public:
//    int minOperations(vector<int>& nums, int x)
//    {
//        //其实是 两端连续的 数组的和为 x
//        //可以把题目转换成  求中间一段连续的数组 和为  整个数组的元素 - x 的最长区间
//        int sum = 0;
//        for (auto e : nums)
//            sum += e;
//
//        int target = sum - x;
//        if (target < 0)
//            return -1;
//
//        // else if(target == 0)
//        //     return nums.size();
//
//        int len = -1;
//        cout << sum << " " << target << endl;
//        for (int left = 0, right = 0, sum2 = 0; right < nums.size(); ++right)
//        {
//            sum2 += nums[right];
//            while (sum2 > target)
//            {
//                sum2 -= nums[left++];
//            }
//            if (sum2 == target)
//            {
//                len = max(len, right - left + 1);
//                // cout << len <<endl;
//            }
//        }
//
//        return len == -1 ? -1 : nums.size() - len;
//
//    }
//};




//https://leetcode.cn/problems/next-greater-element-i/description/
//496. 下一个更大元素 I
//nums1 中数字 x 的 下一个更大元素 是指 x 在 nums2 中对应位置 右侧 的 第一个 比 x 大的元素。
//给你两个 没有重复元素 的数组 nums1 和 nums2 ，下标从 0 开始计数，其中nums1 是 nums2 的子集。
//对于每个 0 <= i < nums1.length ，找出满足 nums1[i] == nums2[j] 的下标 j ，并且在 nums2 确定 nums2[j] 的 下一个更大元素 。如果不存在下一个更大元素，那么本次查询的答案是 - 1 。
//返回一个长度为 nums1.length 的数组 ans 作为答案，满足 ans[i] 是如上所述的 下一个更大元素 。
//
//输入：nums1 = [4, 1, 2], nums2 = [1, 3, 4, 2].
//输出：[-1, 3, -1]
//解释：nums1 中每个值的下一个更大元素如下所述：
//- 4 ，用加粗斜体标识，nums2 = [1, 3, 4, 2]。不存在下一个更大元素，所以答案是 - 1 。
//- 1 ，用加粗斜体标识，nums2 = [1, 3, 4, 2]。下一个更大元素是 3 。
//- 2 ，用加粗斜体标识，nums2 = [1, 3, 4, 2]。不存在下一个更大元素，所以答案是 - 1


class Solution {
public:
    //打印栈函数
    void Print(stack<int> st)
    {
        while (!st.empty())
        {
            cout << st.top() << "->";
            st.pop();
        }
        cout << endl;
    }
    vector<int> nextGreaterElement(vector<int>& nums1, vector<int>& nums2)
    {
        vector<int> ret;
        stack<int> st;
        unordered_map<int, int> hash;
        for (int i = 0; i < nums2.size(); ++i)
            hash[nums2[i]] = i;

        for (int i = 0; i < nums1.size(); ++i)
        {
            st.push(nums1[i]);
            int j = hash[nums1[i]] + 1; //找到下一个数的下标

            //开始入栈，单调递减栈 栈顶遇到第一个比自己大的数就出栈
            //Print(st);
            while (!st.empty() && j < nums2.size())
            {
                //如果下一个元素小于 栈顶元素，就入栈，保持单调递减
                if (nums2[j] < st.top())
                    st.push(nums2[j]);

                while (!st.empty() && nums2[j] > st.top())
                    st.pop();

                j++;
            }
            //到这里栈为空 或者 j 越界 说明之前最开始插入的
            if (st.empty())
                ret.push_back(nums2[j - 1]);
            else
                ret.push_back(-1);

            //清空 st 里面的元素 因为有可能是由于 数组越界判断出来的，栈不为空
            while (!st.empty())
                st.pop();
        }
        return ret;
    }
};




//35. 搜索插入位置
//给定一个排序数组和一个目标值，在数组中找到目标值，并返回其索引。如果目标值不存在于数组中，返回它将会被按顺序插入的位置。
//请必须使用时间复杂度为 O(log n) 的算法。
//输入: nums = [1, 3, 5, 6], target = 5
//输出 : 2

class Solution {
public:

    // int searchInsert(vector<int>& nums, int target) 
    // {
    //     //先判断是否小于最小值
    //     if(target <= nums[0])
    //         return 0;
    //     //有序 考虑二分
    //     int left = 0, right = nums.size() - 1;
    //     int mid = 0;  
    //     //考虑用一个值来记录 
    //     int ret = nums.size();
    //     while(left <= right)
    //     {
    //         mid = (right + left) >> 1;
    //         if(target <= nums[mid])
    //         {
    //             //ret 一定是比 mid 下标左边 很巧
    //             ret = mid;
    //             right = mid - 1;
    //         }
    //         else
    //             left = mid + 1;
    //     }
    //     return ret;
    // }

    int searchInsert(vector<int>& nums, int target)
    {
        //先判断是否小于最小值
        if (target <= nums[0])
            return 0;
        //有序 考虑二分
        int left = 0, right = nums.size() - 1;
        int mid = 0;
        while (left <= right)
        {
            mid = (left + right) >> 1;
            if (target > nums[mid])
                left = mid + 1;
            else if (target < nums[mid])
                right = mid - 1;
            else
            {
                //找到了目标值 返回下标
                return mid;
            }
        }
        //说明没有找到  错的  最后很难分出是 mid 的位置
        return left;
    }
};



//https://leetcode.cn/problems/fruit-into-baskets/description/
//904. 水果成篮
//输入：fruits = [3, 3, 3, 1, 2, 1, 1, 2, 3, 3, 4]
//输出：5
//解释：可以采摘[1, 2, 1, 1, 2] 这五棵树。

// 还是用滑动窗口做，只能有两个篮子，每个篮子可以装同一种水果不限个数
class Solution {
public:
    int totalFruit(vector<int>& fruits)
    {
        unordered_map<int, int> hash;
        int count = 0;
        int sum = 0;

        for (int left = 0, right = 0; right < fruits.size(); ++right)
        {
            //开始进窗口
            hash[fruits[right]]++;
            while (hash.size() > 2)
            {
                //说明种类数已经大于 2 了, 要开始左边出窗口
                hash[fruits[left]]--;
                if (hash[fruits[left]] == 0)
                {
                    //删除元素
                    hash.erase(fruits[left]);
                }
                left++;
            }
            sum = max(sum, right - left + 1);
        }
        return sum;
    }
};


// class Solution {
// public:
//     int totalFruit(vector<int>& fruits) 
//     {
//         unordered_map<int, int> hash;
//         int count = 0;
//         int sum = 0;

//         for(int left = 0, right = 0; right < fruits.size(); ++right)
//         {
//             //说明两个篮子中有还没有水果
//             if(hash[fruits[right]] == 0)
//             {
//                 count++;
//             }
//             hash[fruits[right]]++;
//             //如果count = 3
//             while(count > 2)
//             {
//                 hash[fruits[left]]--;
//                 if(hash[fruits[left]] == 0) //说明最左端的水果个数已经清空了
//                     count--;
//                 left++;
//             }
//             sum = max(sum, right- left + 1);
//         }
//         return sum;
//     }
// };


// class Solution {
// public:
//     int totalFruit(vector<int>& fruits) 
//     {
//         unordered_map<int, int> hash;
//         int count = 0;
//         int sum = 0;

//         for(int left = 0, right = 0; right < fruits.size(); ++right)
//         {
//             //说明两个篮子中有还没有水果
//             if(hash[fruits[right]] == 0)
//             {
//                 count++;
//             }
//             hash[fruits[right]]++;

//             //如果count = 3
//             cout << count << endl;

//             // 这样写也通过了 但是写的很捞啊 while 比较用count更好控制
//             if(count == 3)
//             {
//                 //开始出窗口
//                 while(hash[fruits[left]] != 0)
//                 {
//                     hash[fruits[left]]--;
//                     if(hash[fruits[left]] == 0)
//                         break;
//                     left++;                    
//                 }
//                 left++;
//                 count--;
//             }
//             sum = max(sum, right- left + 1);
//         }

//         return sum;
//     }
// };




//https://leetcode.cn/problems/keep-multiplying-found-values-by-two/description/
//2154. 将找到的值乘以 2
class Solution {
public:
    int findFinalValue(vector<int>& nums, int original)
    {
        unordered_map<int, int> hash;
        for (auto e : nums)
            hash[e]++;
        //不用在意是否重复 找不找的到就完事了    
        while (hash.find(original) != hash.end())
            original *= 2;

        return original;

    }
};


//*******   这题 还可以在看一下 还有一种算法  KMP  算法   ********//
//https://leetcode.cn/problems/find-the-index-of-the-first-occurrence-in-a-string/description/
//28. 找出字符串中第一个匹配项的下标
//给你两个字符串 haystack 和 needle ，请你在 haystack 字符串中找出 needle 字符串的第一个匹配项的下标（下标从 0 开始）。
//如果 needle 不是 haystack 的一部分，则返回 - 1 。

class Solution {
public:
    int strStr(string haystack, string needle)
    {
        //方法1 用库函数可以解决
        // size_t pos = haystack.find(needle);
        // if(pos == string::npos)
        //     return -1;
        // return pos;

        // size_t pos = haystack.find(needle);
        // return (int)pos;

        //这三种方法都可以  最标准的是返回 size_t 的一个类型
        // int pos = haystack.find(needle);
        // return pos;

        //方法2 暴力求解
        for (int i = 0; i < haystack.size(); ++i)
        {
            int flag = 1;
            for (int j = 0; j < needle.size(); ++j)
            {
                //如果相等就一直比较  不相等就退出
                if (haystack[i + j] != needle[j])
                {
                    flag = 0;
                    break;
                }
            }

            if (flag == 1)
                return i;
        }
        return -1;
    }
};




//https://leetcode.cn/problems/plus-one/description/
//给定一个由 整数 组成的 非空 数组所表示的非负整数，在该数的基础上加一。
//最高位数字存放在数组的首位， 数组中每个元素只存储单个数字。
//你可以假设除了整数 0 之外，这个整数不会以零开头。
//输入：digits = [1, 2, 3]
//输出：[1, 2, 4]
//解释：输入数组表示数字 123。
class Solution {
public:
    vector<int> plusOne(vector<int>& digits)
    {
        vector<int> retv;
        //加法呗
        int n = digits.size();
        int carry = 0;
        //最好不要改变原数组 digits 最好新建一个变量

        reverse(digits.begin(), digits.end());
        digits[0]++;
        for (int i = 0; i < n; i++)
        {
            digits[i] += carry;
            if (digits[i] == 10)
            {
                carry = 1;
                digits[i] = 0;
            }
            else
                carry = 0;
        }
        if (carry == 1)
        {
            digits.push_back(1);
        }
        reverse(digits.begin(), digits.end());

        return digits;
    }

    //还不能这么做 long long 类型还不够长
    // vector<int> plusOne(vector<int>& digits) 
    // {
    //     long long  sum = 0;
    //     vector<int> retv;
    //     //输入先转换成数字
    //     for(auto e : digits)
    //         sum = sum * 10 + e;

    //     //然后+1在放回数组
    //     sum++; 
    //     while(sum)
    //     {
    //         retv.push_back(sum % 10);
    //         sum /= 10;
    //     }
    //     reverse(retv.begin(), retv.end());

    //     return retv;
    // }
};



//https://leetcode.cn/problems/binary-tree-paths/description/
//257. 二叉树的所有路径
//给你一个二叉树的根节点 root ，按 任意顺序 ，返回所有从根节点到叶子节点的路径。
//叶子节点 是指没有子节点的节点。
//输入：root = [1, 2, 3, null, 5]
//输出：["1->2->5", "1->3"]


/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */


class Solution {
public:
    vector<string> binaryTreePaths(TreeNode* root)
    {
        vector<string> contain;
        if (!root) return {};
        string base = to_string(root->val);
        _binaryTreePaths(root, base, contain);
        return contain;

    }
    //需要用一个str来记录字符串
    void _binaryTreePaths(TreeNode* root, string str, vector<string>& contain)
    {
        if (root == nullptr)
            return;
        //根左右
        if (root->left == nullptr && root->right == nullptr)
        {
            contain.push_back(str);
            return;
        }

        //如果左节点不为空
        if (root->left)
        {
            _binaryTreePaths(root->left, str + "->" + to_string(root->left->val), contain);
        }
        if (root->right)
        {
            _binaryTreePaths(root->right, str + "->" + to_string(root->right->val), contain);
        }

    }

};

// class Solution {
// public:
//     vector<string> binaryTreePaths(TreeNode* root) 
//     {
//          if(!root) return {};
//          string base=to_string(root->val);
//          vector<string>contain;
//          _binaryTreePaths(root ,base,contain);
//          return contain;
//     }
//     void _binaryTreePaths(TreeNode* root,string str,vector<string>&contain)
//     {
//         if(!root->left&&!root->right) 
//         {
//             contain.push_back(str);
//             return ;
//         }
//         if(root->left)
//         {
//             string temp=str+"->"+to_string(root->left->val);
//             _binaryTreePaths(root->left,temp,contain);
//         }
//         if(root->right)
//         {
//              string temp=str+"->"+to_string(root->right->val);
//             _binaryTreePaths(root->right,temp,contain);
//         }
//     }

// };


// class Solution {
// public:
//     vector<string> binaryTreePaths(TreeNode* root) 
//     {
//          if(!root) return {};
//          string base=to_string(root->val);
//          vector<string>contain;
//          _binaryTreePaths(root ,base,contain);
//          return contain;
//     }
//     void _binaryTreePaths(TreeNode* root,string& str,vector<string>&contain)
//     {
//         if(!root->left&&!root->right) 
//         {
//             contain.push_back(str);
//             return ;
//         }
//         if(root->left)
//         {
//             string temp=to_string(root->left->val);
//             str+="->"+temp;
//             _binaryTreePaths(root->left,str,contain);
//             for(int i=0;i<temp.size()+2;++i)
//             {
//                 str.pop_back();
//             }
//         }
//         if(root->right)
//         {
//             string temp=to_string(root->right->val);
//             str+="->"+temp;
//             _binaryTreePaths(root->right,str,contain);
//             for(int i=0;i<temp.size()+2;++i)
//             {
//                 str.pop_back();
//             }
//         }
//     }

// };


//https://leetcode.cn/problems/best-time-to-buy-and-sell-stock/description/
//121. 买卖股票的最佳时机

class Solution {
public:
    int maxProfit(vector<int>& prices)
    {
        int profit = 0;
        int cost = INT_MAX;
        for (int i = 0; i < prices.size(); ++i)
        {
            cost = min(cost, prices[i]);
            profit = max(profit, prices[i] - cost);
        }

        return profit;
    }
};


//https://leetcode.cn/problems/VabMRr/submissions/
//LCR 015. 找到字符串中所有字母异位词
//滑动窗口
#include <unordered_map>
class Solution {
public:
    //方法2 数组直接比较
    vector<int> findAnagrams(string s, string p)
    {
        unordered_map<char, int> hash1;
        unordered_map<char, int> hash2;
        for (auto e : p)
            hash1[e]++;
        //不知道是不是能有重复元素 这里默认 p 无重复元素 --有重复元素的
        //现在 hash 的大小是 p.size()
        int psize = p.size();
        vector<int> retv;
        int count = 0;
        for (int left = 0, right = 0; right < s.size(); ++right)
        {
            //进窗口
            hash2[s[right]]++;

            //判断 维护这一段固定区间
            if (right - left + 1 > psize)
            {
                //说明需要出窗口
                hash2[s[left]]--;
                left++;
            }

            //可能没到 psize，也可能是经过上面判断后出来 刚好是psize个
            if (check(hash1, hash2))
            {
                retv.push_back(left);
            }

        }
        return retv;
    }

    bool check(unordered_map<char, int>& hash1, unordered_map<char, int>& hash2)
    {
        //比较两个hash表是否相同  还挺麻烦的 auto for其实是迭代器
        //map中的一个元素是  pair 类型
        for (auto it : hash1)
        {
            auto it2 = hash2.find(it.first);
            if (it2 == hash2.end())
            {
                //说明找不到退出
                return false;
            }
            if (it.second != it2->second)
                return false;
        }
        return true;
    }

    //方法1 用一个count来维护有效字符的个数
// 其实用数组模拟hash表也是可以的
// int hash1[26] = {0}; int hash2[26] = {0}
    vector<int> findAnagrams2(string s, string p)
    {
        unordered_map<char, int> hash1;
        unordered_map<char, int> hash2;
        for (auto e : p)
            hash1[e]++;
        int psize = p.size();
        vector<int> retv;

        int count = 0; //记录有效字符的个数
        for (int left = 0, right = 0; right < s.size(); ++right)
        {
            ++hash2[s[right]];
            //判断是否为有效字符
            auto it1 = hash1.find(s[right]);
            if (it1 != hash1.end() && it1->second >= hash2[s[right]])
            {
                //hash1中的值 >= hash2中的值 说明这个是有效值
                count++;
            }

            if (right - left + 1 > psize)
            {
                auto it = hash1.find(s[left]);
                //这里也要 维护count
                if (it != hash1.end() && it->second >= hash2[s[left]])
                {
                    count--;
                }
                //出窗口
                hash2[s[left]]--;
                left++;
            }

            if (count == psize)
            {
                retv.push_back(left);
            }
        }

        return retv;
    }

};


//https://leetcode.cn/problems/binary-search/submissions/
//704. 二分查找
class Solution {
public:
    int search(vector<int>& nums, int target)
    {
        int left = 0, right = nums.size() - 1;
        while (left <= right)
        {
            int mid = (left + right) >> 1;
            if (target == nums[mid])
            {
                return mid;
            }
            else if (target > nums[mid])
            {
                left = mid + 1; //或者 ++mid  不能 ++mid 奥
            }
            else
                right = mid - 1; //或者 --mid
        }
        return -1;
    }
};



//34. 在排序数组中查找元素的第一个和最后一个位置
//https://leetcode.cn/problems/find-first-and-last-position-of-element-in-sorted-array/description/
class Solution {
public:
    vector<int> searchRange(vector<int>& nums, int target)
    {
        if (nums.size() == 0)
        {
            return { -1, -1 };
        }

        int left = 0, right = nums.size() - 1;
        vector<int> retv;
        //先找出左边界
        while (left <= right)
        {
            int mid = (left + right) >> 1;
            if (target <= nums[mid])
                right = mid - 1;
            else
                left = mid + 1;
        }

        //如果target 在数组中没有被找到 返回
        if (left > nums.size() - 1 || nums[left] != target)
            return { -1,-1 };

        retv.push_back(left);

        left = 0; right = nums.size() - 1;
        while (left <= right)
        {
            int mid = (left + right) >> 1;
            if (target >= nums[mid])
                left = mid + 1;
            else
                right = mid - 1;
        }
        retv.push_back(right);

        return retv;
    }
};


//2487. 从链表中移除节点
//https://leetcode.cn/problems/remove-nodes-from-linked-list/description/?envType=daily-question&envId=2024-01-03

class Solution {
public:
    ListNode* removeNodes(ListNode* head)
    {
        stack<int> single_st;

        //构建一个单调递减栈
        ListNode* cur = head;
        while (cur)
        {
            //如果为空 或者栈顶元素 大于等于 当前值 就入栈
            if (single_st.empty() || cur->val <= single_st.top())
            {
                single_st.push(cur->val);
            }
            else if (cur->val > single_st.top())
            {
                //否则 就一直出栈 一直到栈为空 或者 栈顶元素 大于 当前值
                while (!single_st.empty() && single_st.top() < cur->val)
                {
                    single_st.pop();
                }
                single_st.push(cur->val);
            }
            cur = cur->next;
        }

        // 判断 元素
        // while(!single_st.empty())
        // {
        //     cout<< single_st.top() << " ";
        //     single_st.pop();
        // }

        //头插 有点忘了
        ListNode* newhead = nullptr;
        while (!single_st.empty())
        {
            ListNode* tmp = new ListNode(single_st.top());
            single_st.pop();
            tmp->next = newhead;
            newhead = tmp;
        }
        return newhead;
    }
};



// LCR 015. 找到字符串中所有字母异位词
// https://leetcode.cn/problems/VabMRr/
#include<string>

class Solution {
public:
    vector<int> findSubstring(string s, vector<string>& words)
    {
        unordered_map<string, int> hash1;
        unordered_map<string, int> hash2;
        vector<int> retv;
        for (auto e : words)
            hash1[e]++;

        //words中每一个单词的大小
        int len = words[0].size(); int count = 0;

        //总共需要 len 次外循环
        for (int i = 0; i < len; ++i)
        {
            //hash2 需要清空 
            hash2.clear();
            count = 0;
            for (int left = i, right = i; right < s.size(); right += len)
            {
                string stmp = s.substr(right, len);
                hash2[stmp]++;
                //查看此字符串在hash1中是否存在
                if (hash1.count(stmp) > 0)
                {
                    //查看此字符串出现了几次
                    if (hash2[stmp] <= hash1[stmp])
                    {
                        //说明有效
                        count++;
                    }
                }

                if (right - left + 1 > len * words.size())
                {
                    //判断是否要出窗口  出窗口的时候判断是否是有效字符串 维护 count
                    string stmp2 = s.substr(left, len);
                    if (hash1.count(stmp2) > 0 && hash2[stmp2] <= hash1[stmp2])
                    {
                        count--;
                    }
                    hash2[stmp2]--;
                    left += len;
                }

                if (count == words.size())
                {
                    retv.push_back(left);
                }
            }
        }

        return retv;
    }
};

//https://leetcode.cn/problems/jJ0w9p/submissions/
//LCR 072. x 的平方根
class Solution {
public:
    int mySqrt(int x)
    {
        //如果小于 1 的数， 开平方取整一定是0
        if (x < 1)
            return 0;

        int left = 1, right = x;
        //二段性
        //  x = 8
        // [1  4]  [9  16  25  36]
        //  1  2    3   4   5   6
        //   目标
        while (left < right)  //left < right 退出时left 和 right 相等
        {
            long long mid = left + (right - left + 1) / 2;  //这里就要 + 1
            if (mid * mid <= x)
                left = mid;
            else
                right = mid - 1;  //这里 -1
        }

        return left;
    }
};


//https://leetcode.cn/problems/ransom-note/submissions/?envType=daily-question&envId=2024-01-07
//383. 赎金信

class Solution {
public:
    bool canConstruct(string ransomNote, string magazine)
    {
        unordered_map<char, int> hash1;
        //创建一个 哈希表，统计元素个数
        for (auto e : magazine)
            hash1[e]++;

        //查找 ransomNote 数组
        for (auto e : ransomNote)
        {
            //如果 字符在 hash1 中存在
            if (hash1.count(e) > 0 && hash1[e] > 0)
                hash1[e]--;
            else //字符不在hash1中
                return false;
        }

        return true;
    }
};


//https://leetcode.cn/problems/minimum-string-length-after-removing-substrings/
//2696. 删除子串后的字符串最小长度

class Solution {
public:
    int minLength(string s)
    {
        stack<char> st;
        for (int i = 0; i < s.size(); ++i)
        {
            //首先要判断非空！！ 跌了一个大坑  不然 st.top 会有问题
            if (!st.empty() && ((s[i] == 'B' && st.top() == 'A') || (s[i] == 'D' && st.top() == 'C')))
            {
                st.pop();
            }
            else
            {
                st.push(s[i]);
            }
        }

        return st.size();
    }
};



//2645. 构造有效字符串的最少插入数
//https://leetcode.cn/problems/minimum-additions-to-make-valid-string/?envType=daily-question&envId=2024-01-11
class Solution {
public:
    int addMinimum(string word)
    {
        //再使用一个字符串 使用双指针对这两个字符串进行遍历，如果字符不相同说明需要插入新字符
        //用 j %= 3 来控制对 "abc" 的轮询
        //看答案做的
        int count = 0;
        int n = word.size();
        string cmp = "abc";
        //逆天错误 ，这里 "abc" 写成了 "adc"
        int i = 0, j = 0;
        while (i < n)
        {
            if (word[i] == cmp[j])
            {
                i++;
                j++;
            }
            else
            {
                j++;
                count++;
            }
            j %= 3;

        }

        if (word.back() == 'a')
            count += 2;
        else if (word.back() == 'b')
            count++;

        return count;
    }
};



//https://leetcode.cn/problems/B1IidL/submissions/
//LCR 069. 山脉数组的峰顶索引

int peakIndexInMountainArray(vector<int>& arr)
{
    int left = 0, right = arr.size() - 1;
    while (left < right)
    {
        int mid = left + (right - left) / 2;
        //如果查到了山峰右区间
        if (arr[mid] > arr[mid + 1])
        {
            right = mid;
        }
        else if (arr[mid] < arr[mid + 1])
        {
            left = mid + 1;
        }
    }
    return left;
}



//https://leetcode.cn/problems/count-common-words-with-one-occurrence/submissions/?envType=daily-question&envId=2024-01-12
//2085. 统计出现过一次的公共字符串

int countWords(vector<string>& words1, vector<string>& words2)
{
    unordered_map<string, int> hash1;
    unordered_map<string, int> hash2;

    for (auto& c : words1)
        hash1[c]++;
    for (auto& c : words2)
        hash2[c]++;

    int count = 0;
    //用 auto
    for (auto str : words1)
    {
        if (hash2.count(str) > 0)
        {
            if (hash1[str] == 1 && hash2[str] == 1)
                count++;
        }
    }

    //或者用普通
    // for(int i = 0; i < words1.size(); ++i)
    // {
    //     if(hash2.count(words1[i]) > 0)
    //     {
    //         if(hash1[words1[i]] == 1 && hash2[words1[i]] == 1)
    //             count++;
    //     }
    // }

    return count;
}


//83. 删除排序链表中的重复元素
//https://leetcode.cn/problems/remove-duplicates-from-sorted-list/?envType=daily-question&envId=2024-01-14

class Solution {
public:
    ListNode* deleteDuplicates(ListNode* head)
    {
        if (head == nullptr)
            return nullptr;
        //再写一次 
        ListNode* phead, * tail, * cur;
        phead = tail = cur = head;
        int temp_val = cur->val;
        while (cur)
        {
            if (cur->val != temp_val)
            {
                tail->next = cur;
                tail = tail->next;
                temp_val = cur->val;
            }
            cur = cur->next;
        }

        //注意 尾需要置为空  不然会连接回之前的 链表上
        tail->next = nullptr;
        return phead;
    }
};


//https://leetcode.cn/problems/find-peak-element/submissions/
//162. 寻找峰值

int findPeakElement(vector<int>& nums)
{
    int left = 0; int right = nums.size() - 1;
    while (left < right)
    {
        int mid = left + (right - left + 1) / 2;
        if (nums[mid] > nums[mid - 1])
            left = mid;
        else
            right = mid - 1;
    }
    return left;
}


// int findPeakElement(vector<int>& nums) 
// {
//     //二段性 -∞ 可以看成  [-1, 1, 2, 1, 3, 5, 6, 4, -1]; 一定是存在山峰值的
//     // 如果 [mid] < [mid+1] 最大值一定在右边
//     // 如果 [mid] > [mid+1] 最大值一定在左边

//     int left = 0; int right = nums.size()-1;
//     while(left < right)
//     {
//         int mid = left + (right - left)/2;
//         if(nums[mid] < nums[mid+1])
//         {
//             left = mid + 1;
//         }
//         else
//         {
//             right = mid;
//         }
//     }

//     return left;
// }


//https://leetcode.cn/problems/remove-duplicates-from-sorted-list-ii/?envType=daily-question&envId=2024-01-15
//82. 删除排序链表中的重复元素 II

ListNode* deleteDuplicates(ListNode* head)
{
    if (head == nullptr)
        return nullptr;

    ListNode* cur = head;
    // ListNode* newhead = head;
    // ListNode* tail = head;


    ListNode* newhead = new ListNode(0);
    ListNode* tail = newhead;

    while (cur)
    {
        if (cur->next == nullptr || cur->val != cur->next->val)
        {
            tail->next = cur;
            tail = tail->next;
            cur = cur->next;
        }
        else if (cur->val == cur->next->val)
        {
            int temp_val = cur->val;
            while (cur && temp_val == cur->val)
            {
                cur = cur->next;
            }
        }
    }

    tail->next = nullptr;

    return newhead->next;
}



//https://leetcode.cn/problems/search-in-rotated-sorted-array/
//33. 搜索旋转排序数组

int search(vector<int>& nums, int target)
{
    int left = 0, right = nums.size() - 1;
    int n = nums.size();
    int x = nums[0];

    while (left <= right)
    {
        int mid = left + (right - left) / 2;
        cout << mid << " ";
        if (nums[mid] == target)
            return mid;

        if (nums[mid] >= nums[0])
        {
            //说明mid左边是升序大数组
            if (nums[0] <= target && target < nums[mid])
            {
                right = mid - 1;
            }
            else
            {
                left = mid + 1;
            }
        }
        else
        {
            //说明mid右边是升序小数组
            if (nums[mid] < target && target <= nums[n - 1])
            {
                left = mid + 1;
            }
            else
            {
                right = mid - 1;
            }
        }
    }

    return -1;
}


//https://leetcode.cn/problems/find-maximum-number-of-string-pairs/submissions/
//2744. 最大字符串配对数目

int maximumNumberOfStringPairs(vector<string>& words)
{
    unordered_map<string, int> hash1;
    int count = 0;
    for (int i = 0; i < words.size(); ++i)
    {
        //进hash前进行判断，如果当前字符串的反转字符串在 hash表中存在 count就+1
        if (hash1.count(reverse_string(words[i])) > 0)
            count++;
        else
            hash1[words[i]]++;
    }
    return count;
}

string reverse_string(string s1)
{
    reverse(s1.begin(), s1.end());
    return s1;
}



//https://leetcode.cn/problems/find-minimum-in-rotated-sorted-array/submissions/
//153. 寻找旋转排序数组中的最小值

int findMin(vector<int>& nums)
{
    //选择参考点 A --- B  还是 C --- D
    //          4 5 6 7       0 1 2 3      如果是 0 1 2 3 4 5 6 7 选择左边为参考点会有问题 需要判断边界
    //二分查找  找出二段性 二段性就是 这两个升序数组段 将数组分割成了两段
    // mid 在 左边区间 说明最小值在 mid 的右边
    // mid 在 右边区间 说明最小值在 mid 的左边
    int left = 0, right = nums.size() - 1;
    int n = nums.size();
    while (left < right)
    {
        int mid = left + (right - left) / 2;
        if (nums[mid] > nums[n - 1])
        {
            //如果 mid 查找出来是在左边区间 那么左边区间的所有的值肯定是 大于 右边区间的
            left = mid + 1;
        }
        else
        {
            //说明 mid 查找出来在右边区间 那么应该继续向左边找 
            //应防止越界
            right = mid;
        }
    }
    return nums[left];
}


//https://leetcode.cn/problems/linked-list-cycle-ii/submissions/
//142. 环形链表 II

class Solution {
public:
    ListNode* detectCycle(ListNode* head)
    {
        //用hash表
        unordered_map<ListNode*, int> hash;
        ListNode* cur = head; int i = 0;
        while (cur)
        {
            //当链表不为空
            hash[cur]++;
            if (hash[cur] == 2)
                return cur;
            cur = cur->next;
        }
        return nullptr;
    }
};


//https://leetcode.cn/problems/longest-consecutive-sequence/?envType=study-plan-v2&envId=top-100-liked
//128. 最长连续序列

int longestConsecutive(vector<int>& nums)
{
    if (nums.empty())
        return 0;

    //先排序
    sort(nums.begin(), nums.end());
    int len = -1;
    int count = 1;
    for (int i = 1; i < nums.size(); ++i)
    {
        if (nums[i] == nums[i - 1])
            continue;

        if (nums[i] == nums[i - 1] + 1)
        {
            count++;
        }
        else
        {
            count = 1;
        }

        len = max(len, count);
    }
    return len == -1 ? 1 : len;
}



//https://leetcode.cn/problems/removing-minimum-number-of-magic-beans/submissions/
//2171. 拿出最少数目的魔法豆

long long minimumRemoval(vector<int>& beans)
{
    int n = beans.size(); long long sum = 0; long long min_sum = LLONG_MAX;
    //先排序 从前向后遍历
    sort(beans.begin(), beans.end());
    for (auto& e : beans)
        sum += e;

    //可以搞一个数组来记录，每一个 dp 位置下面放 此beans元素下的要拿出的最多豆子
    //然后对数组以此进行比较即可
    vector<long long> dp(n, 0);
    for (int i = 0; i < n; ++i)
    {
        dp[i] = sum - (long long)beans[i] * (n - i);
        min_sum = min(dp[i], min_sum);
    }
    return min_sum;
}


//https://leetcode.cn/problems/range-sum-query-immutable/submissions/?envType=list&envId=po2kNwiQ
//303. 区域和检索 - 数组不可变

class NumArray {
public:
    //经典前缀和问题  求数组一段区间的和 
    vector<int> dq;
    NumArray(vector<int>& nums)
    {
        //用 nums 初始化一个新数组 dq 
        //dq 下标用来存放每一个 数组之前范围的全部和
        // dq.push_back(0);  错  思路不行
        //还得先为 dq 数组开空间 不然无法[]访问

        dq.resize(nums.size() + 1, 0);
        for (int i = 1; i <= nums.size(); ++i)
        {
            dq[i] = dq[i - 1] + nums[i - 1];
        }
    }

    int sumRange(int left, int right)
    {
        return dq[right + 1] - dq[left];
    }
};



//https://leetcode.cn/problems/split-strings-by-separator/submissions/?envType=daily-question&envId=2024-01-20
//2788. 按分隔符拆分字符串

vector<string> splitWordsBySeparator(vector<string>& words, char separator)
{
    //方法2
    vector<string> ret;
    for (string& word : words)
    {
        //将每一个 words 中的元素 放入到 stream 流里
        stringstream ss(word);

        //从 流对象中 读取 字符到 str 中， delim 是分割符
        // istream& getline (istream& is, string& str, char delim);
        string sub;
        //sub 默认是""空字符串
        //当前流中 $easy$  
        //提取子串，如果遇到分隔符就不提取，否则就一直提取到分隔符前为止
        //同时再次提取会覆盖 sub 中原有字串信息
        while (getline(ss, sub, separator))
        {
            if (!sub.empty())
                ret.push_back(sub);
        }
    }

    return ret;
}

// vector<string> splitWordsBySeparator(vector<string>& words, char separator) 
// {
//     //方法1
//     vector<string> ret;
//     for(int i = 0; i < words.size(); ++i)
//     {
//         int left = 0;
//         int pos = words[i].find(separator,left);
//         //如果找不到 直接将整个字符串 push
//         if(pos == string::npos)
//             ret.push_back(words[i].substr(left, string::npos));

//         //如果找到了
//         while(pos != string::npos)
//         {
//             //如果找到在字符串中存在 分隔符
//             //判断是不是空字符串  是空字符串就不入
//             if(left != pos)
//                 ret.push_back(words[i].substr(left, pos-left));

//             left = pos+1; //指向下一个位置

//             pos = words[i].find(separator, left);
//             if(pos == string::npos && left < words[i].size()) // && 后面这个语句是打的补丁
//                 ret.push_back(words[i].substr(left, string::npos));
//         }

//     }

//     return ret;
// }

// vector<string> splitWordsBySeparator(vector<string>& words, char separator) 
// {
//     //方法1
//     vector<string> ret;
//     for(int i = 0; i < words.size(); ++i)
//     {
//         int left = 0;
//         int pos = words[i].find(separator,left);
//         //如果找不到 直接将整个字符串 push
//         if(pos == string::npos)
//             ret.push_back(words[i].substr(left, string::npos));

//         //如果找到了
//         while(pos != string::npos)
//         {
//             //如果找到在字符串中存在 分隔符
//             cout<<"left = " <<left <<" pos ="<<pos<<endl;
//             //判断是不是空字符串  是空字符串就不入
//             if(left != pos)
//             {
//                 ret.push_back(words[i].substr(left, pos-left));
//             }

//             cout<<words[i].substr(left, pos-left)<<" "<<endl;
//             left = pos+1;
//             pos = words[i].find(separator, left);
//             if(pos == string::npos && left < words[i].size())
//             {
//                 ret.push_back(words[i].substr(left, string::npos));
//             }
//         }

//     }

//     return ret;
// }




//https://leetcode.cn/problems/n-th-tribonacci-number/description/
//1137. 第 N 个泰波那契数

int tribonacci(int n)
{
    //方法2 dp 可以用 滚动数组 来进行优化  减小空间复杂度
    //n < 3 的时候要单独判断 不然用 dp 数组会越界
    if (n == 0)
        return 0;
    if (n == 1 || n == 2)
        return 1;

    int a = 0, b = 1, c = 1, d = 0;
    for (int i = 3; i <= n; ++i)
    {
        d = a + b + c;
        //赋值  滚动数组
        a = b;
        b = c;
        c = d;
    }

    return d;
}

// int tribonacci(int n) 
// {
//     //方法1 dp
//     //n < 3 的时候要单独判断 不然用 dp 数组会越界
//     if(n == 0)
//         return 0;
//     if(n == 1 || n == 2)
//         return 1;

//     vector<int> dp(n+1);
//     dp[0] = 0; dp[1] = 1; dp[2] = 1;
//     for(int i = 3; i <= n; ++i)
//     {
//         dp[i] = dp[i-3] + dp[i-2] + dp[i-1];
//     }

//     return dp[n];
// }


//https://leetcode.cn/problems/roman-to-integer/submissions/
//13. 罗马数字转整数

int romanToInt(string s)
{
    unordered_map<char, int> hash = { {'I', 1},{'V', 5},{'X',10},{'L', 50},
                                        {'C', 100},{'D', 500},{'M',1000} };
    //先定义一个 hash 数组
    //罗马数字 组合字符 都是前面比后面的大， 如果前面比后面小，置为负号
    int sum = 0;
    for (int i = 1; i < s.size(); ++i)
    {
        if (hash[s[i - 1]] < hash[s[i]])
            sum -= hash[s[i - 1]];
        else
            sum += hash[s[i - 1]];
    }
    //因为最后一个数没有加  所以最后加上去
    sum += hash[s[s.size() - 1]];
    return sum;
}



//https://leetcode.cn/problems/three-steps-problem-lcci/
//面试题 08.01. 三步问题
int waysToStep(int n)
{
    //建立dp表

    //处理边界条件
    if (n == 1 || n == 2)
        return n;
    if (n == 3)
        return 4;
    vector<long long> dp(n + 1);

    long long MOD = 1e9 + 7;
    dp[1] = 1; dp[2] = 2; dp[3] = 4;
    for (int i = 4; i <= n; i++)
    {
        dp[i] = (dp[i - 1] + dp[i - 2] + dp[i - 3]) % MOD;
    }

    return dp[n];
}



//https://leetcode.cn/problems/maximum-swap/?envType=daily-question&envId=2024-01-22
//670. 最大交换

class Solution {
public:
    // int maximumSwap(int num) 
    // {
    //     //向后查找第一个最小的值 并且做记录 然后向后查找最大值
    //     //转换成字符串 to_string
    //     string nums = to_string(num);
    //     int min_idex = 0; int max_idex = 0; int flag = 0; int max_number = 0;
    //     for(int i = 0; i < nums.size(); ++i)
    //     {
    //         if(i + 1 < nums.size() && flag == 0 && nums[i] <= nums[i+1])
    //         {
    //             min_idex = i;
    //             flag = 1;
    //         }
    //         if(flag == 1 && nums[i] >= max_number)
    //         {
    //             max_number = nums[i];
    //             max_idex = i;
    //         }
    //     }
    //     if(nums[min_idex] == '0')
    //         --min_idex;
    //     swap(nums[min_idex], nums[max_idex]);
    //     // cout << min_idex << " " << nums[min_idex]<<" " << max_idex;
    //     cout << min_idex << " " << max_idex;
    //     return stoi(nums);
    // }

    //没做出来 答案有点不理解   以后再看看吧 感觉上面的做法再做一下应该能做出来
    //从后向前遍历
    int maximumSwap(int num)
    {
        string nums = to_string(num);
        int n = nums.size();
        int min_idex = -1; int m_idex = n - 1;  int max_idex = -1;
        for (int i = n - 1; i >= 0; --i)
        {
            if (nums[i] > nums[m_idex])
            {
                m_idex = i;
            }
            else if (nums[i] < nums[m_idex])
            {
                min_idex = i;
                max_idex = m_idex;
            }
        }
        if (min_idex >= 0)
        {
            swap(nums[min_idex], nums[max_idex]);
            return stoi(nums);
        }
        else
            return num;

    }

};



//https://leetcode.cn/problems/longest-alternating-subarray/solutions/2610815/zui-chang-jiao-ti-zi-xu-lie-by-leetcode-2aevc/?envType=daily-question&envId=2024-01-23
//2765. 最长交替子数组

int alternatingSubarray(vector<int>& nums)
{
    int n = nums.size(), len = -1, res = -1;
    //用 i 来表示当前位置的下标
    for (int i = 0; i < n; ++i)
    {
        int flag = 1;
        for (int j = i; j + 1 < n; j++)
        {
            if (nums[j + 1] - nums[j] == flag)
            {
                flag *= -1;
                if (len == -1)
                    len = 1;
                len++;
            }
            else
                break;
        }

        //判断 以当前 i 为下标的时候 最长的交替子数组的长度;
        res = max(res, len);
        if (len != -1)
            len = 1;
    }
    return res == 1 ? res + 1 : res;
}




//https://leetcode.cn/problems/beautiful-towers-i/solutions/2614597/mei-li-ta-i-by-leetcode-solution-uqnf/?envType=daily-question&envId=2024-01-24
//2865. 美丽塔 I

class Solution {
public:
    long long maximumSumOfHeights(vector<int>& maxHeights)
    {
        long long sum = 0; int n = maxHeights.size();
        long long res = 0;
        for (int i = 0; i < n; ++i)
        {
            //采用两层for循环 先求出 山顶左边元素的和 在求出山顶右边元素的和
            int sum_left = maxHeights[i];
            for (int j = i - 1; j >= 0; j--)
            {
                sum_left = min(sum_left, maxHeights[j]);
                sum += sum_left;
            }

            int sum_right = maxHeights[i];
            for (int j = i + 1; j < n; j++) //j = i + 1   和 j = i 的时候合并  也是一样的
            {
                sum_right = min(sum_right, maxHeights[j]);
                sum += sum_right;
            }

            //最后加上 山顶元素的值
            sum += maxHeights[i];

            //比较 i 为山顶元素下标时候的数组的最大值
            res = max(res, sum);
            sum = 0;
        }
        return res;
    }
};



//https://leetcode.cn/problems/sum-of-values-at-indices-with-k-set-bits/submissions/?envType=daily-question&envId=2024-01-25
//2859. 计算 K 置位下标对应元素的和

int sumIndicesWithKSetBits(vector<int>& nums, int k)
{
    long long sum = 0;
    for (int i = 0; i < nums.size(); ++i)
    {
        int n = i;
        int count = 0;
        //计算每一个数 二进制位中1的个数
        while (n > 0)
        {
            n &= n - 1;
            count++;
            //cout<<"uo";
        }
        if (count == k)
        {
            sum += nums[i];
        }
    }
    return sum;
}

//错误示范   用 i &= i-1会改变 i , i一直都是0 会死循环
// int sumIndicesWithKSetBits(vector<int>& nums, int k) 
// {
//     long long sum = 0;
//     for(int i = 0; i < nums.size(); ++i)    
//     {
//         cout<< i;
//         int count = 0;
//         //计算每一个数 二进制位中1的个数
//         while(i>0)
//         {
//             i &= i-1; //i一直都是0
//             count++;
//             //cout<<"uo";
//         }
//         if(count == k)
//         {
//             cout<< i<<" "<<nums[i];
//             sum += nums[i];
//         }
//     }
//     return sum;
// }


//https://leetcode.cn/problems/min-cost-climbing-stairs/submissions/
//746. 使用最小花费爬楼梯

int minCostClimbingStairs(vector<int>& cost)
{
    //状态表示 dp 里面的值来表示到这一层所需要的钱的数量
    //每次爬两个台阶 当前dp[i] 和前两个 dp[i-1] dp[i-2] 有关
    //边界处理 没有看清
    //可以从 0 或者 1 开始爬楼梯  所以 台阶 0 , 1 的所需费用应该为 0
    int n = cost.size();
    vector<int> dp(n + 1, 0);
    dp[0] = dp[1] = 0;
    dp[2] = min(cost[0], cost[1]);
    for (int i = 3; i <= n; ++i)
    {
        dp[i] = min(dp[i - 1] + cost[i - 1], dp[i - 2] + cost[i - 2]);
        //cout<< dp[i] <<" ";
    }
    return dp[n];
}


//https://leetcode.cn/problems/decode-ways/submissions/
//91.解码方法

class Solution {
public:
    int numDecodings(string s)
    {
        //226其实是分成 两部分  一种是i单独能被解码的  
        //                     2  2  6  ，  22   6
        //还有一种是合并的       2   26
        //将这两种方法相加
        //看onenote 题解
        int n = s.size();
        vector<int> dp(n, 0);
        //*********************
        // if(s[0] == '0')
        //     return 0;
        // 
        // if(s[0] != '0')
        //     dp[0] = 1;
        //********************
        //或者这一段可以这样写
        dp[0] = s[0] != '0';

        //先处理前两个数
        //注意输入的范围  有可能只输入一个数
        if (n == 1)
            return dp[0];
        //如果能单个解码 范围在1-9
        if (s[0] != '0' && s[1] != '0')
            dp[1] += 1;
        //如果两个字母合起来也能解码 就说明有两种情况 
        int tmp = (s[0] - '0') * 10 + s[1] - '0';
        if (tmp >= 10 && tmp <= 26) //需要避免 01 02 情况
            dp[1] += 1;

        for (int i = 2; i < n; ++i)
        {
            //如果能单个解码 他的总数范围和dp[i-1]是一样的
            if (s[i] != '0')
                dp[i] += dp[i - 1]; //dp[i]默认全初始化为0
            //两个字符合起来 他的总数范围和dp[i-2]是一样的
            int tmp = (s[i - 1] - '0') * 10 + s[i] - '0';
            if (tmp >= 10 && tmp <= 26)
                dp[i] += dp[i - 2];
        }
        return dp[n - 1];
    }

    //坏  写的是错的！
    //     int numDecodings(string s) 
    //     {
    //         //状态表示  dp[i] 用来表示当前元素下总共能有多少种映射方法
    //         //可以看出来, 最多只能 两个字母 来组合
    //         //比如11206 两个1有两种组合方式 1 1   11
    //         //那么i = 2 的时候 所能和前面一个的组合数 最多是两种 最少是一种
    //         //只有可能是 1 2 或者 12 都是合法的
    //         //也就是到下标2 的时候的组合数 是 1 1 2 或者 11 2 或者 1 12
    //         //如果是 0 和前面一个数字2只有一种组合方法 ，需要 -1
    //         //前   合法     不合法     合法     合法
    //         //后   不合法   合法       合法     合法
    //         //合   合法     不合法     合法     不合法
    //         //总数  +1      不变       +1       不变

    //         //先判断前缀0
    //         if(s[0] == '0')
    //             return 0;
    //         int n = s.size();
    //         vector<int> dp(n, 0);
    //         dp[0] = 1;
    //         for(int i = 1; i < n; ++i)
    //         {
    //             if(s[i-1] != '0' && s[i] != '0')
    //             {
    //                 //再判断是不是两个数字合在一起是不是合法
    //                 if(stoi(s.substr(i-1,2)) <= 26)
    //                 {
    //                     dp[i] = dp[i-1]+1;
    //                 }
    //             }
    //             else if(s[i-1] != '0' && s[i] == '0')
    //             {
    //                 if(stoi(s.substr(i-1,2)) <= 26)
    //                 {
    //                     dp[i] = dp[i-1]-1;
    //                 }
    //                 else
    //                     return 0;
    //             }
    //             else
    //             {
    //                 dp[i] = dp[i-1];
    //             }

    //         }
    //         return dp[n-1];
    //     }
};


<<<<<<< HEAD

/*����һ�β������  �����ն��ύ */
=======
//https://leetcode.cn/problems/range-sum-of-bst/?envType=daily-question&envId=2024-02-26
//938. 二叉搜索树的范围和


class Solution {
public:

    void dfs(TreeNode* root, int& low, int& high, int& res)
    {
        if(root == nullptr)
            return;
        
        //如果当前值小于 low 值 ，说明比low大的值可能在右边
        if(root->val < low)
            dfs(root->right, low, high, res);

        //如果当前值大于 high 值，说明比high小的值可能在左边
        if(root->val > high)
            dfs(root->left, low, high, res);

        //如果在范围内 就加上去， 并且继续向左右两边去寻找
        if(root->val >= low && root->val <= high)
        {
            res += root->val;
            dfs(root->left, low, high, res);
            dfs(root->right, low, high, res);
        }
    
    }


    int rangeSumBST(TreeNode* root, int low, int high) 
    {
        int res = 0;
        dfs(root, low, high, res);
        return res;
    }
};


//https://leetcode.cn/problems/unique-paths/description/
//62. 不同路径


class Solution {
public:
    int uniquePaths(int m, int n)
    {
        //1.创建dp表
        vector<vector<int>> dp(m + 1, vector<int>(n + 1, 0));

        //初始化第一个数
        dp[0][1] = 1;

        //3行
        for (int i = 1; i < m + 1; ++i)
        {
            //从左向右填
            for (int j = 1; j < n + 1; ++j)
            {
                dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
            }
        }

        return dp[m][n];
    }
};


//235. 二叉搜索树的最近公共祖先
//https://leetcode.cn/problems/lowest-common-ancestor-of-a-binary-search-tree/description/?envType=daily-question&envId=2024-02-25
class Solution {
public:
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q)
    {
        TreeNode* father = root;

        //利用二叉搜索树的性质
        while (true)
        {
            if (p->val < father->val && q->val < father->val)
            {
                father = father->left;
            }
            else if (p->val > father->val && q->val > father->val)
            {
                father = father->right;
            }
            else
            {
                break;
            }

        }

        return father;
    }
};


//94. 二叉树的中序遍历
//https://leetcode.cn/problems/binary-tree-inorder-traversal/description/?envType=daily-question&envId=2024-02-10
class Solution {
public:

    void dfs(TreeNode* root, vector<int>& retv)
    {
        if (root == nullptr)
            return;
        dfs(root->left, retv);
        retv.push_back(root->val);
        dfs(root->right, retv);
    }
    vector<int> inorderTraversal(TreeNode* root)
    {
        vector<int> retv;
        dfs(root, retv);
        return retv;
    }
};


//https://leetcode.cn/problems/make-costs-of-paths-equal-in-a-binary-tree/submissions/?envType=daily-question&envId=2024-02-28
//2673. 使二叉树所有路径值相等的最小代价

class Solution {
public:
    int minIncrements(int n, vector<int>& cost)
    {
        int count = 0;
        //利用满二叉树的性质 父亲等于 子/2
        for (int i = n - 2; i >= 0; i -= 2)
        {
            cost[i / 2] += max(cost[i + 1], cost[i]);
            //count = max(cost[i+1], cost[i]) - min(cost[i+1], cost[i]);
            count += abs(cost[i + 1] - cost[i]);
        }
        return count;
    }
};



//105. 从前序与中序遍历序列构造二叉树
//https://leetcode.cn/problems/construct-binary-tree-from-preorder-and-inorder-traversal/submissions/?envType=daily-question&envId=2024-02-20
class Solution {
public:
    unordered_map<int, int> hash;

    TreeNode* my_bulidTree(vector<int>& preorder, vector<int>& inorder, int pre_left, int pre_right,
        int inorder_left, int inorder_right)
    {
        //[ 3 (9 2)  20 15 7]
        //[(2 9) 3   15 20 7]
        if (pre_left > pre_right)
            return nullptr;

        //前序遍历第一个元素就是 根的位置，先记录下来
        int preorder_root = pre_left;

        //找到 这个根在 中序数组中的位置
        int inorder_root = hash[preorder[pre_left]];

        //那么此时说明在中序数组中 根左边的就是 当前根的 左子树， 右边的就是 右子树
        //那么也需要记录在前序数组中， 那几个是 前序数组中 当前根的 左子树
        int left_SubTree_Size = inorder_root - inorder_left;

        //先构建一个节点
        TreeNode* root = new TreeNode(preorder[preorder_root]); //preorder[pre_left]也是可以的

        //开始递归
        //当前根的左子树的范围 
        //在前序数组中就 [pre_left+1, pre_left+subsize] 在中序数组中就是[inorder_left, inorder_root-1]
        //先序遍历中「从 左边界+1 开始的 size_left_subtree」个元素就对应了中序遍历中「从 左边界 开始到 根节点定位-1」的元素
        root->left = my_bulidTree(preorder, inorder, pre_left + 1, pre_left + left_SubTree_Size, inorder_left, inorder_root - 1);
        //右子树的范围
        //在前序数组中就 先序遍历中「从 左边界+1+左子树节点数目 开始到 右边界」的元素就对应了中序遍历中「从 根节点定位+1 到 右边界」的元素
        root->right = my_bulidTree(preorder, inorder, pre_left + left_SubTree_Size + 1, pre_right, inorder_root + 1, inorder_right);
        //注意是 右边界而不是简单的 n-1
        return root;
    }

    TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder)
    {
        int n = preorder.size();
        //构造hash映射
        for (int i = 0; i < n; ++i)
            hash[inorder[i]] = i;

        TreeNode* root = my_bulidTree(preorder, inorder, 0, n - 1, 0, n - 1);
        return root;
    }
};


//写两个判断条件的函数
bool valid_TWo(int x, int y)
{
    return x == y;
}

bool valid_Three(int x, int y, int z)
{
    return (x == y && y == z) || (x + 1 == y && y + 1 == z);
}
bool validPartition(vector<int>& nums)
{
    //动态规划来做
    //1.状态表示  dp[i] 用来表示是否能划分 1为可以划分
    //2.状态转移方程 dp[i] = dp[i-2]

    int n = nums.size();
    vector<int> dp(n + 1, false);
    //初始化 0 给 1 从下标为 1 开始 可以判读为两个的时候的值
    dp[0] = 1;
    cout << dp[0] << " ";
    for (int i = 1; i <= n; ++i)
    {
        if (i >= 2)
        {
            //当前值有两种状态 
            //1. 要想能分割 说明前(n−2)个元素组成的数组至少存在一个有效划分，且后两个元素相等
            //为什么是 -1  -2 
            dp[i] = dp[i - 2] && valid_TWo(nums[i - 1], nums[i - 2]);
        }
        if (i >= 3)
        {
            //2. 说明前(n-3)个元素组成的数是有效划分，且最后三个元素满足题目条件
            //但是已经有可能 已经满足 前(n-2)个元素的条件了， 所以得用 或 以免原来已经满足的条件被覆盖
            dp[i] = dp[i] || (dp[i - 3] && valid_Three(nums[i - 3], nums[i - 2], nums[i - 1]));
        }
        cout << dp[i] << " ";
    }

    return dp[n];

}



//https://leetcode.cn/problems/unique-paths-ii/submissions/
//63. 不同路径 II

class Solution {
public:
    int uniquePathsWithObstacles(vector<vector<int>>& obstacleGrid)
    {
        //和不同路径1 类似
        int m = obstacleGrid.size();
        int n = obstacleGrid[0].size();
        vector<vector<int>> dp(m + 1, vector<int>(n + 1, 0));

        dp[0][1] = 1;

        for (int i = 1; i <= m; ++i)
        {
            for (int j = 1; j <= n; ++j)
            {
                if (obstacleGrid[i - 1][j - 1] == 1)
                    dp[i][j] = 0;
                else
                    dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
            }
        }


        return dp[m][n];
    }
};


//https://leetcode.cn/problems/implement-stack-using-queues/?envType=daily-question&envId=2024-03-03
//225. 用队列实现栈
class MyStack {
public:
    //一种方法就是 两个队列进行倒，可以参考当时C语言的写法
    //还有一种写法就是只用 q1, q2用来做辅助判断 最后用swap进行交换
    //这里尝试用第二种写法

     MyStack() {}

     //改成用指针也可以 但是后面成员函数调用要变成 这里就不做备份了 _q2->push(x);
     // MyStack() 
     // {
     //     _q1 = new queue<int>;
     //     _q2 = new queue<int>;
     // }

     // ~MyStack()
     // {
     //     delete _q1;
     //     delete _q2;
     // }

     void push(int x) 
     {
         _q2.push(x);
         while(!_q1.empty())
         {
             int val = _q1.front();
             _q1.pop();
             _q2.push(val);
         }
         //所有元素都被换到队列2 中 然后队列1,2交换
         //C++11公共成员函数  也可以写成 _q1.swap(_q2); 估计重载了 ()
         swap(_q1, _q2);
     }

     int pop() {
         int val = _q1.front();
         _q1.pop();
         return val;
     }

     int top() {
         return _q1.front();
     }

     bool empty() {
         return _q1.empty();
     }


private:
    queue<int> _q1;
    queue<int> _q2;

    // queue<int>* _q1;
    // queue<int>* _q2;
};



//https://leetcode.cn/problems/implement-queue-using-stacks/submissions/
//232. 用栈实现队列

class MyQueue {
public:
    MyQueue() {

    }

    void push(int x) {
        _pushst.push(x);
    }

    int pop() {
        // if(_popst.empty())
        // {
        //     //如果pop栈为空 说明要先从 push栈中将数据倒过来
        //     while(!_pushst.empty())
        //     {
        //         int val = _pushst.top();
        //         _pushst.pop();
        //         _popst.push(val);
        //     }
        // }

        //int ret = _popst.top();

        int ret = peek();
        _popst.pop();

        return ret;
    }

    int peek()
    {
        if (_popst.empty())
        {
            while (!_pushst.empty())
            {
                int val = _pushst.top();
                _pushst.pop();
                _popst.push(val);
            }
        }
        return _popst.top();
    }

    bool empty() {
        return _pushst.empty() && _popst.empty();
    }

private:
    stack<int> _pushst;
    stack<int> _popst;
};




//https://leetcode.cn/problems/li-wu-de-zui-da-jie-zhi-lcof/submissions/
//LCR 166. 珠宝的最高价值

class Solution {
public:
    int jewelleryValue(vector<vector<int>>& frame)
    {
        //建立dp表
        //当前的价值和 它的左边和上边有联系
        //因为他是从左上开始走 只能走右边或者下边
        int m = frame.size();
        int n = frame[0].size();
        vector<vector<int>> dp(m + 1, vector<int>(n + 1, 0));

        for (int i = 1; i <= m; ++i)
        {
            for (int j = 1; j <= n; ++j)
            {
                // 当前dp数组的值 代表当前位置最大的价值，需要再加上 frame中当前位置的价值 才是
                // 在当前位置上的最高价值
                dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]) + frame[i - 1][j - 1];
            }
        }

        return dp[m][n];
    }
};



//https://leetcode.cn/problems/minimum-falling-path-sum/submissions/
//931. 下降路径最小和

class Solution {
public:
    int minFallingPathSum(vector<vector<int>>& matrix)
    {
        //dp表中的值代表 到这一个位置时的最小和， 然后在加上matrix中的值 就是当前的最小和了
        //所以当前dp表中的值和它的左上方，上方，右下方的最小和
        //初始化建立 多一行，两列    极限情况下最大值100*100 选整形最大值作为 无穷大没问题
        int m = matrix.size();
        int n = matrix[0].size();

        vector<vector<int>> dp(m + 1, vector<int>(n + 2, INT_MAX));

        //然后把第一行的 dp 元素置为 0
        for (int j = 0; j < n + 2; ++j)
            dp[0][j] = 0;

        //开始 dp 数组的计算
        for (int i = 1; i <= m; ++i)
        {
            for (int j = 1; j <= n; ++j)
            {
                //使用 C++11 的初始化列表来 比较多个数的大小
                dp[i][j] = min({ dp[i - 1][j - 1], dp[i - 1][j], dp[i - 1][j + 1] }) + matrix[i - 1][j - 1];

                //不然使用常规方法
                //dp[i][j] = min(min(dp[i-1][j-1], dp[i-1][j]), dp[i-1][j+1]) + matrix[i-1][j-1];
            }
        }

        //求出最后一行的 最小的路径是多少
        int min_sum = INT_MAX;
        for (int i = 1; i <= n; ++i)
            min_sum = min(min_sum, dp[m][i]);

        return min_sum;
    }
};



//https://leetcode.cn/problems/find-the-k-or-of-an-array/description/?envType=daily-question&envId=2024-03-06
//2917. 找出数组中的 K-or 值

class Solution {
public:
    //可以通过
    // int findKOr(vector<int>& nums, int k) 
    // {
    //     int n = nums.size();
    //     int sum = 0;
    //     for(int j = 0; j < 32; ++j)
    //     {
    //         int count = 0;
    //         for(int i = 0; i < n; ++i)
    //         { 
    //             //这里只能 强转成 long 类型 doule 转 long ，强转成 int 会报错
    //             if(((long)pow(2.0, j) & (long)nums[i]) == (long)pow(2.0, j))
    //                 count++;
    //         }
    //         if(count >= k)
    //             sum += pow(2.0, j);
    //     }
    //     return sum;
    // }

    int findKOr(vector<int>& nums, int k)
    {
        int n = nums.size();
        int K_or = 0;
        for (int j = 0; j < 31; ++j)
        {
            int count = 0;
            for (int i = 0; i < n; ++i)
            {
                //经典右移一位 和 1 按位 &
                if ((nums[i] >> j) & 1 == 1)
                    count++;
            }
            if (count >= k)
                K_or += (1 << j);
        }
        return K_or;
    }
};



//https://leetcode.cn/problems/minimum-path-sum/submissions/
//64. 最小路径和

class Solution {
public:
    int minPathSum(vector<vector<int>>& grid)
    {
        //dp
        int m = grid.size();
        int n = grid[0].size();
        //先初始化为 INT_MAX ，因为求最小路径 如果初始化为 0 会有问题
        //但是也要保证第一个数 是原来表格的值
        vector<vector<int>> dp(m + 1, vector<int>(n + 1, INT_MAX));

        dp[0][1] = dp[1][0] = 0;
        for (int i = 1; i <= m; ++i)
        {
            for (int j = 1; j <= n; ++j)
            {
                dp[i][j] = min(dp[i - 1][j], dp[i][j - 1]) + grid[i - 1][j - 1];
            }
        }
        return dp[m][n];
    }
};



//https://leetcode.cn/problems/find-the-divisibility-array-of-a-string/submissions/?envType=daily-question&envId=2024-03-07
//2575. 找出字符串的可整除数组

class Solution {
public:
    vector<int> divisibilityArray(string word, int m)
    {
        int n = word.size();
        vector<int> div(n, 0);
        long long sum = 0;
        for (int i = 0; i < n; ++i)
        {
            //此处对 m 取模， 防止过大 如果前面能取模 数字会变小
            sum = (sum * 10 + word[i] - '0') % m;

            if (sum % m == 0)
                div[i] = 1;
        }
        return div;
    }
};




//反转部分单向链表
struct ListNode
{
    int val;
    ListNode* next;
    ListNode() : val(0), next(nullptr) {}

    ListNode(int x) : val(x), next(nullptr) {}
    ListNode(int x, ListNode* next) : val(x), next(next) {}
};


ListNode* reverse_part(ListNode* head, int left, int right)
{
    ListNode* cur = head;
    //先找到 left 前一个的节点   方便之后链接
    //这里要先记录一下 不然会出错
    int left_find = left;
    while (--left_find)
    {
        cur = cur->next;
    }

    ListNode* left_node_pre = cur;
    ListNode* left_node = cur->next;

    cur = cur->next;

    //计算节点数量 
    int node_lenth = right - left + 1;

    //反转部分链表
    ListNode* newhead = nullptr;
    while (node_lenth--)
    {
        //第一次进来cur 和 left_node 是一样的
        ListNode* next = cur->next;
        cur->next = newhead;
        newhead = cur;
        cur = next;
    }
    //出来后 cur 在 right 节点的下一个位置
    //链接
    left_node_pre->next = newhead;
    left_node->next = cur;

    return head;
}

int main()
{
    int n = 0;
    int val;
    while (~scanf("%d", &n))
    {
        ListNode* head = new ListNode(-1);
        ListNode* cur = head;
        while (n--)
        {
            cin >> val;
            ListNode* tail = new ListNode(val);
            cur->next = tail;
            cur = cur->next;
        }
        cur->next = nullptr;

        int left = 0, right = 0;
        cin >> left >> right;

        //链表创建完毕， 开始部分反转
        ListNode* newhead = reverse_part(head, left, right);

        //打印部分反转后链表
        ListNode* newcur = newhead->next;
        while (newcur)
        {
            cout << newcur->val << " ";
            newcur = newcur->next;
        }
        //删除 new 出来的节点
    }

    return 0;
}


//https://leetcode.cn/problems/remove-nth-node-from-end-of-list/submissions/
//19. 删除链表的倒数第 N 个结点

ListNode* removeNthFromEnd(ListNode* head, int n)
{
    //创建一个哨兵头节点
    ListNode* phead = new ListNode(-1, head);
    ListNode* fast = head;
    ListNode* slow = phead;

    while (n--)
        fast = fast->next;
    //这里之前没有用 phead，而是再一个链表上走 让fast多走一步，如果先遇到了nullptr 就直接返回空
    //但是是有问题的 head = [1], n = 1 --->[] 可以通过
    // head = [1,2], n = 2  ---> [2] 也会返回 []  这是错的
    // 看题解后 用另一个phead让slow 慢一步

    //fast 这样寻找到nullptr 的时候 slow 刚好是要删除的节点
    //但是需要的是 slow 前面一个节点，所以需要再定义一个 phead 
    //slow 从 phead 开始走 慢一步， fast 到 nullptr 的时候 slow 刚好是要删除节点的前一个
    while (fast)
    {
        fast = fast->next;
        slow = slow->next;
    }

    ListNode* delete_node = slow->next;
    slow->next = slow->next->next;
    delete delete_node;

    return phead->next;

}




//https://leetcode.cn/problems/the-masseuse-lcci/submissions/
//面试题 17.16. 按摩师

int massage(vector<int>& nums)
{
    int size = nums.size();
    vector<int> dp(size + 2, 0);
    for (int i = 2; i < size + 2; ++i)
    {
        dp[i] = max(dp[i - 2] + nums[i - 2], dp[i - 1]);
    }
    return dp[size + 1];
}

// //方法2 i 有多种情况
// int massage(vector<int>& nums)
// {
//     int n = nums.size();
//     if(n == 0)
//         return 0;

//     vector<int> f(n, 0);
//     auto g = f; //拷贝一个和 f 一样的数组
//     //假设 i 位置的时候，f 代表要选上当前 nums[i]的值 g 表示不选当前nums[i]的值

//     f[0] = nums[0];
//     for(int i = 1; i < n; ++i)
//     {
//         f[i] = g(i-1) + nums[i];
//         g[i] = max(f(i-1), g(i-1));
//     }
//     return max(f[n-1], g[n-1]);
// }




//174. 地下城游戏
//https://leetcode.cn/problems/dungeon-game/

class Solution {
public:
    int calculateMinimumHP(vector<vector<int>>& dungeon)
    {
        //和以往不同， 如果以某一个位置为结尾  dp[i][j] 表示从起点出发到[i, j]位置的时候，所需要的最低健康初始点数 无法推导
        //如果以某一个位置为起点 dp[i][j] 表示从[i, j]位置出发，到达终点，所需要的最低初始健康点数
        //填表顺序从下往上 从右往左

        int m = dungeon.size();
        int n = dungeon[0].size();
        //建立dp
        vector<vector<int>> dp(m + 1, vector(n + 1, INT_MAX));

        //初始化
        dp[m][n - 1] = dp[m - 1][n] = 1;

        for (int i = m - 1; i >= 0; --i)
        {
            for (int j = n - 1; j >= 0; --j)
            {
                dp[i][j] = min(dp[i][j + 1], dp[i + 1][j]) - dungeon[i][j];
                //例如 示例1 dungeon 数组值为 30 的位置
                //如果 dungeon[i][j] 很大,那么dp[i][j]的值可能会是一个负数 30 位置dp[i][j] 表示最少 -24 血量才能到终点
                //这显然是不对的，血量不能为负数， 如果是负数应该 置为 1 最低血量只能为1 不能为负数
                dp[i][j] = max(1, dp[i][j]);
            }
        }

        return dp[0][0];
    }
};





//https://leetcode.cn/problems/capitalize-the-title/
//2129. 将标题首字母大写
class Solution {
public:
    string capitalizeTitle(string t)
    {
        //先拷贝一个一样的数组
        string title(t);
        title.push_back(' '); //后面再加上一个' ' 以免处理后续情况  
        int n = title.size();
        for (int left = 0, right = 0; right < n; ++right)
        {
            if (title[right] == ' ')
            {
                if (right - left > 2)
                {
                    //这里不能使用 title[left] = toupper(title[left++]);
                    //++优先级比 = 要高
                    title[left] = toupper(title[left]);
                    left++;
                    while (left < right)
                    {
                        title[left] = tolower(title[left]);
                        ++left;
                    }
                }
                else
                {
                    while (left < right)
                    {
                        title[left] = tolower(title[left]);
                        ++left;
                    }
                }
                ++left;
            }
        }
        title.pop_back();
        return title;
    }
};



//https://leetcode.cn/problems/find-elements-in-a-contaminated-binary-tree/submissions/511009386/
//1261. 在受污染的二叉树中查找元素

class FindElements {
public:
    void dfs(TreeNode* root, int val)
    {
        if (root == nullptr)
            return;

        root->val = val;
        dfs(root->left, val * 2 + 1);
        dfs(root->right, val * 2 + 2);
    }

    FindElements(TreeNode* root)
    {
        _root = root;
        dfs(_root, 0);

    }

    bool _find(TreeNode* root, int target)
    {
        if (root == nullptr)
            return false;
        if (root->val == target)
            return true;
        return _find(root->left, target) || _find(root->right, target);

    }

    bool find(int target)
    {
        return _find(_root, target);
    }

private:
    TreeNode* _root = nullptr;
};

/**
 * Your FindElements object will be instantiated and called as such:
 * FindElements* obj = new FindElements(root);
 * bool param_1 = obj->find(target);
 */



//https://leetcode.cn/problems/maximum-odd-binary-number/?envType=daily-question&envId=2024-03-13
//2864. 最大二进制奇数
class Solution {
public:
    string maximumOddBinaryNumber(string s1)
    {
        string s(s1);
        int left = 0, right = s.size() - 1;
        if (right == 0)
            return s;

        while (left < right)
        {
            while (s[left] != '0' && left < right)
                ++left;
            while (s[right] != '1' && left < right)
                --right;
            swap(s[left], s[right]);
        }
        swap(s[right - 1], s[s.size() - 1]);
        return s;
    }
};




//https://leetcode.cn/problems/largest-element-in-an-array-after-merge-operations/?envType=daily-question&envId=2024-03-14
//2789. 合并后数组中的最大元素

long long maxArrayValue(vector<int>& nums)
{
    int n = nums.size();
    long long max_val = nums[n - 1];
    for (int i = n - 2; i >= 0; --i)
    {
        max_val = max_val >= nums[i] ? max_val + nums[i] : nums[i];
    }

    return max_val;
}

// long long maxArrayValue(vector<int>& nums) 
// {
//     int n = nums.size();
//     //vector<long> dp(n, 0);
//     long long max_val = 0;
//     for(int i = n-1; i >= 0; --i)
//     {
//         long long sum = 0;
//         int j = i;
//         long long value = 0;
//         while(j > 0 && nums[i] >= nums[j-1])
//         {
//             value += nums[j-1];
//             --j;
//         }
//         cout << value <<" ";
//         max_val = max_val > value ? max_val : value;
//     }

//     return max_val;
// }




//https://leetcode.cn/problems/longest-common-prefix/
//14. 最长公共前缀
class Solution {
public:
    string longestCommonPrefix(vector<string>& strs)
    {
        int n = strs.size();
        int m = strs[0].size();
        string temp_str;
        char temp_char;

        for (int i = 0; i < m; ++i)
        {
            temp_char = strs[0][i];
            for (int j = 0; j < n; ++j)
            {
                if (strs[j][i] != temp_char)
                    return temp_str;
            }
            temp_str += strs[0][i];
        }
        return temp_str;
    }


    // string longestCommonPrefix(vector<string>& strs) 
    // {
    //     int n = strs.size();
    //     if(n == 1)
    //         return strs[0];
    //     unordered_map<int, string> hash;
    //     string temp_str;
    //     int m = strs[0].size();
    //     for(int i = 0; i < m; ++i)
    //     {
    //         temp_str += strs[0][i];
    //         hash[i] = temp_str;
    //     }
    //     // for(int i = 0; i < m; ++i)
    //     // {
    //     //     cout<< hash[i].c_str() <<" ";
    //     // }

    //     int j = 0; int flag = 0;
    //     while(j < m)
    //     {
    //         for(int i = 0; i < n; ++i)
    //         {
    //             cout<< strs[i].find(hash[j]) <<" ";
    //             if(strs[i].find(hash[j]) != 0)
    //             {
    //                 flag = 1;
    //                 break;
    //             }
    //         }
    //         //cout << flag <<" ";
    //         if(flag == 1)  
    //             break;
    //         j++;          
    //     }
    //     if(flag == 1) 
    //         return hash[j-1];
    //     else
    //         return "";

    // }
};







//https://leetcode.cn/problems/maximum-number-of-moves-in-a-grid/description/?envType=daily-question&envId=2024-03-16
//2684. 矩阵中移动的最大次数

class Solution {
public:
    int maxMoves(vector<vector<int>>& grid)
    {
        int m = grid.size();
        int n = grid[0].size();
        vector<vector<int>> dp(m + 2, vector(n, 0));
        vector<vector<int>> newgrid(m + 2, vector(n, INT_MAX));

        //初始化新grid表
        for (int i = 1; i <= m; ++i)
        {
            for (int j = 0; j < n; ++j)
            {
                newgrid[i][j] = grid[i - 1][j];
            }
        }
        int count = 0;
        for (int j = 1; j < n; ++j)
        {
            for (int i = 1; i <= m; ++i)
            {
                if (newgrid[i][j] > newgrid[i - 1][j - 1] || newgrid[i][j] > newgrid[i][j - 1] || newgrid[i][j] > newgrid[i + 1][j - 1])
                {
                    dp[i][j] = max({ dp[i - 1][j - 1], dp[i][j - 1], dp[i + 1][j - 1] }) + 1;
                    count = max(count, dp[i][j]);
                }
                else
                    newgrid[i][j] = INT_MAX;
            }
        }

        return count;
    }

    // int maxMoves(vector<vector<int>>& grid) 
    // {
    //     int m = grid.size();
    //     int n = grid[0].size();
    //     vector<vector<int>> dp(m+2, vector(n, 0));
    //     vector<vector<int>> newgrid(m+2, vector(n, INT_MAX));
    //     //初始化dp表

    //     // for(int i = 0; i < dp.size(); ++i)
    //     // {
    //     //     for(int j = 0; j < dp[0].size(); ++j)
    //     //     {
    //     //         cout << dp[i][j] << " ";
    //     //     }
    //     //     cout << endl;
    //     // }

    //     //初始化新grid表
    //     for(int i = 1; i <= m; ++i)
    //     {
    //         for(int j = 0; j < n; ++j)
    //         {
    //             newgrid[i][j] = grid[i-1][j];
    //         }
    //     }
    //     // for(int i = 0; i < newgrid.size(); ++i)
    //     // {
    //     //     for(int j = 0; j < newgrid[0].size(); ++j)
    //     //     {
    //     //         cout << newgrid[i][j] << " ";
    //     //     }
    //     //     cout << endl;
    //     // }

    //     int count = 0;
    //     for(int j = 1; j < n; ++j)
    //     {
    //         for(int i = 1; i <= m; ++i)
    //         {
    //             // cout << "newgrid[i][j]:"<<newgrid[i][j]<<" "<<"newgrid[i-1][j-1]:"<<newgrid[i-1][j-1]<<" "<<"newgrid[i][j-1]:"<<newgrid[i][j-1] <<" "<<"newgrid[i+1][j-1]:"<<newgrid[i+1][j-1]<<endl;
    //             // cout << (newgrid[i][j] > newgrid[i-1][j-1])<< " "<<(newgrid[i][j] > newgrid[i][j-1])<<" "<<(newgrid[i][j] > newgrid[i+1][j-1])<<endl;
    //             if(newgrid[i][j] > newgrid[i-1][j-1] || newgrid[i][j] > newgrid[i][j-1] || newgrid[i][j] > newgrid[i+1][j-1])
    //             {
    //                 //cout << "dp[i-1][j-1]:"<<dp[i-1][j-1]<<" "<<"dp[i][j-1]:"<<dp[i][j-1]
    //                 //<<" "<<"dp[i+1][j-1]:"<<dp[i+1][j-1]<<endl;
    //                 dp[i][j] = max({dp[i-1][j-1], dp[i][j-1], dp[i+1][j-1]}) + 1;
    //                 //cout <<"dp[i][j]:"<<dp[i][j]<<endl;
    //                 count = max(count, dp[i][j]);
    //             }
    //             else
    //             {
    //                 newgrid[i][j] = INT_MAX;
    //             }
    //         }
    //     }

    //     return count;
    // }
};




//https://leetcode.cn/problems/string-to-integer-atoi/
//8. 字符串转换整数 (atoi)
class Solution {
public:
    int myAtoi(string s)
    {
        int flag = 1;
        long long num = 0;

        for (int i = 0; i < s.size(); ++i)
        {
            //先清除空格
            while (s[i] == ' ')
                i++;
            //判断±
            if (s[i] == '-')
            {
                flag = -1;
                ++i;
            }
            else if (s[i] == '+')
                ++i;

            //判断数字
            cout << "i " << i << "s[i]:" << s[i];
            while (isdigit(s[i]))
            {
                num = num * 10 + s[i] - '0';
                if (num * flag >= INT_MAX)
                    return INT_MAX;
                else if (num * flag <= INT_MIN)
                    return INT_MIN;
                ++i;
            }

            break;

        }
        return num * flag;
    }
};



//https://leetcode.cn/problems/range-sum-query-immutable/description/?envType=daily-question&envId=2024-03-18
//303. 区域和检索 - 数组不可变

class NumArray {
public:
    //经典前缀和问题  求数组一段区间的和 
    vector<int> dq;
    NumArray(vector<int>& nums)
    {
        //用 nums 初始化一个新数组 dq 
        //dq 下标用来存放每一个 数组之前范围的全部和
        // dq.push_back(0);  错  思路不行
        //还得先为 dq 数组开空间 不然无法[]访问

        dq.resize(nums.size() + 1, 0);
        for (int i = 1; i <= nums.size(); ++i)
        {
            dq[i] = dq[i - 1] + nums[i - 1];
        }
    }

    int sumRange(int left, int right)
    {
        return dq[right + 1] - dq[left];
    }
};



//https://leetcode.cn/problems/add-binary/
//67. 二进制求和

class Solution {
public:
    string addBinary(string a, string b)
    {
        //先翻转字符串 好计算
        reverse(a.begin(), a.end());
        reverse(b.begin(), b.end());

        string str;

        int a_size = a.size(); int b_size = b.size();
        //先补 0 吧
        while (a_size > b_size)
        {
            b.push_back('0'); b_size = b.size();
        }
        while (a_size < b_size)
        {
            a.push_back('0'); a_size = a.size();
        }
        //cout << "a:"<<a.c_str() << " b:"<<b.c_str();
        int carry = 0;
        for (int i = 0; i < a_size; ++i)
        {
            int temp = a[i] - '0' + b[i] - '0' + carry;
            int val = temp % 2;
            carry = temp / 2;
            //推入字符串
            str.push_back(val + '0');
        }
        if (carry == 1)
            str.push_back('1');

        reverse(str.begin(), str.end());
        return str;
    }

    //还有一种写法
    string addBinary(string a, string b)
    {
        //先翻转字符串 好计算
        reverse(a.begin(), a.end());
        reverse(b.begin(), b.end());

        string str;

        int n = max(a.size(), b.size());
        int carry = 0;
        for (int i = 0; i < n; ++i)
        {
            carry += i < a.size() ? (a[i] == '1') : 0;
            carry += i < b.size() ? (b[i] == '1') : 0;
            //推入字符串
            str.push_back((carry % 2 == 1) ? '1' : '0');
            carry /= 2;
        }
        if (carry == 1)
            str.push_back('1');

        reverse(str.begin(), str.end());
        return str;
    }
};



//https://leetcode.cn/problems/partition-list/
//86. 分隔链表
class Solution {
public:
    ListNode* partition(ListNode* head, int x)
    {
        if (head == nullptr)
            return nullptr;
        ListNode* phead = new ListNode(-1, head);
        ListNode* pnewhead = new ListNode(-1, nullptr);

        ListNode* tail = pnewhead;
        ListNode* pre = phead;
        ListNode* cur = pre->next;
        ListNode* next = cur->next;
        while (cur)
        {
            if (cur->val < x)
            {
                tail->next = cur;
                tail = tail->next;

                //原链表连接
                pre->next = next;

                //重新计算节点位置
                cur = next;
                if (cur == nullptr)
                    break;
                next = cur->next;
            }
            else
            {
                pre = cur;
                cur = next;
                if (cur == nullptr)
                    break;
                next = cur->next;
            }

        }

        tail->next = phead->next;
        ListNode* ret_newhead = pnewhead->next;
        delete pnewhead;
        delete phead;

        return ret_newhead;
    }
};



//https://leetcode.cn/problems/frequency-tracker/?envType=daily-question&envId=2024-03-21
//2671. 频率跟踪器
class FrequencyTracker {
private:
    vector<int> _hash;
    vector<int> _fre_hashcnt;
public:
    FrequencyTracker() :_hash(100001), _fre_hashcnt(100001)
    {}

    void add(int number)
    {
        _fre_hashcnt[_hash[number]]--;
        _hash[number]++;
        _fre_hashcnt[_hash[number]]++;
    }

    void deleteOne(int number)
    {
        if (_hash[number] > 0)
        {
            _fre_hashcnt[_hash[number]]--;
            _hash[number]--;
            _fre_hashcnt[_hash[number]]++;
        }

    }

    bool hasFrequency(int frequency)
    {
        return _fre_hashcnt[frequency];
    }
};


//https://leetcode.cn/problems/merge-intervals/submissions/515416591/
//56. 合并区间
class Solution {
public:
    static bool compare(vector<int>& v1, vector<int>& v2)
    {
        return v1[0] < v2[0];
    }

    vector<vector<int>> merge(vector<vector<int>>& intervals)
    {
        vector<vector<int>> retv;
        int m = intervals.size();
        int n = intervals[0].size();

        sort(intervals.begin(), intervals.end());

        // for(int i = 0; i < m; ++i)
        // {
        //     for(int j = 0; j < n; ++j)
        //         cout<< intervals[i][j] <<" ";
        //     cout<< endl;
        // }

        // int left = 0, right = 0;
        // for(int right = 0; right < m; )
        // {
        //     int temp = intervals[right][1];
        //     int begin_left = left;
        //     left = right + 1;
        //     while(left < m && intervals[left][0] <= temp)
        //     {
        //         temp = max(temp, intervals[left][1]);
        //         left++;
        //     }

        //     retv.push_back({intervals[begin_left][0], temp});
        //     left = right;
        // }

        for (int i = 0; i < intervals.size();)
        {
            int t = intervals[i][1];
            int j = i + 1;
            while (j < intervals.size() && intervals[j][0] <= t)
            {
                t = max(t, intervals[j][1]);
                j++;
            }
            retv.push_back({ intervals[i][0], t });
            i = j;
        }


        return  retv;
    }
};


//https://leetcode.cn/problems/count-distinct-numbers-on-board/?envType=daily-question&envId=2024-03-23
//2549. 统计桌面上的不同数字
class Solution {
public:
    int distinctIntegers(int n)
    {
        return  n == 1 ? 1 : n - 1;
    }
};


//这是一行提交测试语句   重装了系统

//https://leetcode.cn/problems/climbing-stairs/submissions/516477998/
//70. 爬楼梯 
class Solution {
public:
    int climbStairs(int n)
    {
        vector<int> dp(n + 1, 0);
        dp[1] = dp[0] = 1;
        for (int i = 2; i <= n; ++i)
            dp[i] = dp[i - 1] + dp[i - 2];
        return dp[n];
    }
};

//https://leetcode.cn/problems/delete-node-in-a-linked-list/
//237. 删除链表中的节点
class Solution {
public:
    void deleteNode(ListNode* node)
    {
        ListNode* next = node->next;
        node->val = next->val;
        node->next = node->next->next;
        delete next;
    }
};



//https://leetcode.cn/problems/sqrtx/
//69. x 的平方根 
int mySqrt(int x)
{
    int left = 0, right = x;
    long long res = 0;
    while (left < right)
    {
        long long mid = left + (right - left) / 2;
        if (mid * mid <= x)
        {
            res = mid;
            left = mid + 1;
        }
        else
            right = mid;
    }
    return x == 1 ? 1 : res;
}


//2810. 故障键盘
//https://leetcode.cn/problems/faulty-keyboard/description/?envType=daily-question&envId=2024-04-01
string finalString(string s)
{
    string ret;
    for (int i = 0; i < s.size(); ++i)
        s[i] == 'i' ? reverse(ret.begin(), ret.end()) : ret.push_back(s[i]);
    return ret;
}

// string finalString(string s) 
// {
//     string ret;
//     int n = s.size();
//     for(int i = 0; i < n; ++i)
//     {
//         if(s[i] == 'i')
//             reverse(ret.begin(), ret.end());
//         else
//             ret.push_back(s[i]);
//     }
//     return ret;
// }



//https://leetcode.cn/problems/word-break/
//139. 单词拆分
class Solution {
public:
    bool wordBreak(string s, vector<string>& wordDict)
    {
        int n = s.size();
        vector<bool> dp(n + 1, false);
        dp[0] = true;
        for (int i = 0; i < n; ++i)
        {
            for (int j = i + 1; j <= n; ++j)
            {
                string sub = s.substr(i, j - i);
                if (find(wordDict.begin(), wordDict.end(), sub) != wordDict.end() && dp[i])
                {
                    dp[j] = true;
                }
            }
        }
        return dp[n];
    }
};


<<<<<<< HEAD
//https://leetcode.cn/problems/best-time-to-buy-and-sell-stock-with-transaction-fee/
//714. 买卖股票的最佳时机含手续费
int maxProfit(vector<int>& prices, int fee)
{
    int n = prices.size();
    vector<vector<int>> dp(n, vector<int>(2));
    //假设dp[i][0] 代表第i天交易完手里没有股票的最大利润
    // dp[i][1]代表交易完后手里有股票的最大利润
    dp[0][0] = 0;
    dp[0][1] = -prices[0];

    for (int i = 1; i < n; ++i)
    {
        dp[i][0] = max(dp[i - 1][0], dp[i - 1][1] + prices[i] - fee);
        dp[i][1] = max(dp[i - 1][1], dp[i - 1][0] - prices[i]);
    }
    return max(dp[n - 1][0], dp[n - 1][1]);
}
=======
//https://leetcode.cn/problems/house-robber/
//198. 打家劫舍
class Solution {
public:
    int rob(vector<int>& nums)
    {
        int n = nums.size();
        vector<int> dp(n + 1);
        dp[1] = nums[0];
        for (int i = 2; i < n + 1; ++i)
        {
            dp[i] = max(dp[i - 2] + nums[i - 1], dp[i - 1]);
            cout << dp[i] << " ";
        }
        return dp[n];
    }
};


//https://leetcode.cn/problems/maximum-difference-between-node-and-ancestor/
//1026. 节点与其祖先之间的最大差值
class Solution {
public:
    void dfs(TreeNode* root, int min_val, int max_val, int& ret)
    {
        if (root == nullptr)
            return;
        ret = max({ ret, abs(root->val - min_val), abs(root->val - max_val) });

        max_val = max(root->val, max_val);
        min_val = min(root->val, min_val);

        //当前root值 减去 当前树上的最大值 或者 最小值 的绝对值 才有可能是最大值V
        dfs(root->left, min_val, max_val, ret);
        dfs(root->right, min_val, max_val, ret);

    }

    int maxAncestorDiff(TreeNode* root)
    {
        int ret = 0;
        dfs(root, root->val, root->val, ret);
        return ret;
    }
};



//https://leetcode.cn/problems/house-robber-ii/
//213. 打家劫舍 II
class Solution {
public:
    int rob(vector<int>& nums)
    {
        int n = nums.size();
        if (n == 1)
            return nums[0];

        vector<int> dp(n + 1);
        vector<int> dp2(n + 1);
        //其实就是在开头在分两种情况，可打家劫舍1 类似
        //如果第一个房间抢了，最后一个房间就不能抢
        //如果第一个房间不抢，最后一个房间可以抢
        dp[1] = nums[0];
        for (int i = 2; i < n; ++i)
            dp[i] = max(dp[i - 2] + nums[i - 1], dp[i - 1]);

        dp2[1] = 0;
        for (int i = 2; i < n + 1; ++i)
            dp2[i] = max(dp2[i - 2] + nums[i - 1], dp2[i - 1]);

        return max(dp[n - 1], dp2[n]);
    }

    //还有就是另外一种写法，使用多状态dp来写 并且将dp过程封装成一个函数
    // int rob(vector<int>& nums) 
    // {
    //     int n = nums.size();
    //     return max(nums[0] + rob1(nums, 2, n-2), rob1(nums, 1, n-1));
    // }
    // int rob1(vector<int>& nums, int left, int right)
    // {
    //     if(left > right) return 0;

    //     int n = nums.size();
    //     vector<int> f(n);
    //     auto g = f;
    //     //初始化
    //     f[left] = nums[left];
    //     for(int i = left+1; i <= right; ++i)
    //     {
    //         f[i] = g[i-1] + nums[i];
    //         g[i] = max(f[i-1], g[i-1]);
    //     }
    //     return max(f[right], g[right]);
    // }

};



//https://leetcode.cn/problems/shan-chu-lian-biao-de-jie-dian-lcof/
//LCR 136. 删除链表的节点
class Solution {
public:
    ListNode* deleteNode(ListNode* head, int val)
    {
        ListNode* phead = new ListNode(-1);
        phead->next = head;
        ListNode* cur = phead;
        while (cur && cur->next)
        {
            ListNode* next = cur->next;
            if (next->val == val)
            {
                cur->next = next->next;
                break;
            }
            cur = cur->next;
        }
        return phead->next;
    }
};


//https://leetcode.cn/problems/delete-and-earn/
//740. 删除并获得点数
int deleteAndEarn(vector<int>& nums)
{
    //建立一个 hash对应数组，下标对应数字， 其中的值代表 这个点数的所有值
    int n = 10001;
    vector<int> hash(n, 0);
    vector<int> dp(n + 1);

    //1.先初始化数组
    for (int i = 0; i < nums.size(); ++i)
        hash[nums[i]] += nums[i];

    for (int i = 0; i < hash.size(); ++i)
    {
        cout << i << ":" << hash[i] << " ";
    }
    cout << endl;
    //统计好数组后 其实就和打家劫舍是一样的 前一个不能偷 后一个不能偷
    dp[1] = hash[0];
    for (int i = 2; i <= n; ++i)
    {
        dp[i] = max(dp[i - 1], dp[i - 2] + hash[i - 1]);
        cout << dp[i] << " ";
    }

    return dp[n];
}



//https://leetcode.cn/problems/JEj789/
//LCR 091. 粉刷房子
class Solution {
public:
    int minCost(vector<vector<int>>& costs)
    {
        //可以用多状态dp来做 也可以就一个单dp来做
        int n = costs.size();
        vector<vector<int>> dp(n + 1, vector<int>(3));
        for (int i = 1; i <= n; ++i)
        {
            for (int j = 0; j < 3; ++j)
            {
                if (j == 0)
                    dp[i][j] = min(dp[i - 1][1], dp[i - 1][2]) + costs[i - 1][0];
                if (j == 1)
                    dp[i][j] = min(dp[i - 1][0], dp[i - 1][2]) + costs[i - 1][1];
                if (j == 2)
                    dp[i][j] = min(dp[i - 1][0], dp[i - 1][1]) + costs[i - 1][2];
            }
        }

        return min({ dp[n][0], dp[n][1], dp[n][2] });
    }

    // int minCost(vector<vector<int>>& costs) 
    // {
    //     //可以用多状态dp来做 也可以就一个单dp来做
    //     //多状态dp 最少花费成本，最后一个粉刷的房子 可能是 红色、蓝色、绿色
    //     //如果最后一个是红色 说明 dp[i][0] = min(dp[i-1][1], dp[i-1][2]) + cost;
    //     //dp[i][0]表示粉刷到i位置时候，i位置上是红色的     
    //     //dp[i][1]表示粉刷到i位置时候，i位置上是蓝色的     
    //     //dp[i][2]表示粉刷到i位置时候，i位置上是绿色的

    //     int n = costs.size();
    //     vector<vector<int>> dp(n+1, vector<int>(3));
    //     for(int i = 1; i <= n; ++i)
    //     {
    //         dp[i][0] = min(dp[i-1][1], dp[i-1][2]) + costs[i-1][0];
    //         dp[i][1] = min(dp[i-1][0], dp[i-1][2]) + costs[i-1][1];
    //         dp[i][2] = min(dp[i-1][0], dp[i-1][1]) + costs[i-1][2];
    //     }     
    //     return min({dp[n][0], dp[n][1], dp[n][2]});
    // }
};



//https://leetcode.cn/problems/best-time-to-buy-and-sell-stock/
//121. 买卖股票的最佳时机
class Solution {
public:
    int maxProfit(vector<int>& prices)
    {
        int n = prices.size();
        vector<int> dp(n);
        dp[0] = 0; int min_val = prices[0]; int max_val = 0;
        for (int i = 1; i < n; ++i)
        {
            min_val = min(min_val, prices[i]);
            dp[i] = prices[i - 1] > prices[i] ? dp[i - 1] : prices[i] - min_val;
            max_val = max(max_val, dp[i]);
        }
        return max_val;
    }
};


class Solution {
public:
    //优化2  提取公共函数

    int binary_search(vector<int>& nums, int val)
    {
        int left = 0; int right = nums.size(); //关键在这里改成 n
        //先找左边界
        while (left < right)
        {
            int mid = left + (right - left) / 2;
            if (nums[mid] >= val)
                right = mid;
            else
                left = mid + 1;
        }
        return left;
    }
    int maximumCount(vector<int>& nums)
    {
        int n = nums.size();
        int left_pos = binary_search(nums, 0);
        int right_pos = binary_search(nums, 1);
        return max(left_pos, n - right_pos);
    }

    // //优化
    // int maximumCount(vector<int>& nums) 
    // {
    //     int n = nums.size();

    //     int left = 0; int right = n; //关键在这里改成 n
    //     //先找左边界
    //     while(left < right)
    //     {
    //         int mid = left + (right - left)/2;
    //         if(nums[mid] >= 0)
    //             right = mid;
    //         else
    //             left = mid + 1;
    //     }

    //     int left_pos = left;

    //     //再找右边界
    //     left = 0; right = n; //关键在这里改成 n
    //     while(left < right)
    //     {
    //         int mid = left + (right - left)/2;
    //         if(nums[mid] >= 1)
    //             right = mid;
    //         else
    //             left = mid + 1;
    //     }
    //     int right_pos = left;

    //     return max(left_pos, n - right_pos);
    // }

    // int maximumCount(vector<int>& nums) 
    // {
    //     int n = nums.size();
    //     cout<<"n: "<<n<<" ";
    //     int left = 0; int right = n-1;
    //     //先找左边界
    //     while(left < right)
    //     {
    //         int mid = left + (right - left)/2;
    //         if(nums[mid] >= 0)
    //             right = mid;
    //         else
    //             left = mid + 1;
    //     }
    //     cout << left<<" ";
    //     int left_pos = left;

    //     //再找右边界
    //     left = 0; right = n-1;
    //     while(left < right)
    //     {
    //         int mid = left + (right - left)/2;
    //         if(nums[mid] >= 1)
    //             right = mid;
    //         else
    //             left = mid + 1;
    //     }
    //     cout << left;
    //     int right_pos = left;
    //     if(left_pos == 0 && right_pos == n-1 && nums[right_pos] == 0)
    //         return 0;
    //     if(right_pos == left_pos && right_pos == n-1)
    //         return n;
    //     return max(left_pos, n - right_pos);
    // }
};


//https://leetcode.cn/problems/maximum-binary-string-after-change/submissions/522256037/?envType=daily-question&envId=2024-04-10
//1702. 修改后的最大二进制字符串
string maximumBinaryString(string binary)
{
    int n = binary.size();
    for (int i = 0, j = 0; i < n; ++i)
    {
        if (binary[i] == '0')
        {
            //找到相邻的两个0  下一个0的位置 中间可以相隔1
            while ((j < n && binary[j] == '1') || j <= i)
            {
                ++j;
            }
            if (j < n)
            {
                binary[j] = '1';
                binary[i] = '1';
                binary[i + 1] = '0';
            }
        }
    }
    return binary;

}


//https://leetcode.cn/problems/best-time-to-buy-and-sell-stock-with-cooldown/
//309. 买卖股票的最佳时机含冷冻期
int maxProfit(vector<int>& prices)
{
    //    假设dp[i][0] 代表第i天交易完处于 买入 状态 此时最大利润  
    //    我们现在有股票，此时不能买股票，只能继续持有股票，或者卖出股票  前一天非冷冻期卖出股票
    //    dp[i][1] 代表第i天之后，处于可交易 状态 此时最大利润 
    //    dp[i][2] 代表第i天之后, 处于 冷冻期 此时最大利润 冷冻期不能到冷冻期 冷冻期可以到可交易 
    int n = prices.size();
    vector<vector<int>> dp(n, vector<int>(3));
    dp[0][0] = -prices[0]; //买入
    for (int i = 1; i < n; ++i)
    {
        dp[i][0] = max(dp[i - 1][0], dp[i - 1][1] - prices[i]);
        dp[i][1] = max(dp[i - 1][1], dp[i - 1][2]);
        dp[i][2] = dp[i - 1][0] + prices[i];
    }
    return max({ dp[n - 1][0], dp[n - 1][1], dp[n - 1][2] });


}


//https://leetcode.cn/problems/maximum-subarray/
//53. 最大子数组和
int maxSubArray(vector<int>& nums)
{
    //dp[i]来表示 以 i 为位置下标的时候所有子数组的最大和
    //可以分层两部分 长度为1 本身， 长度>1 ，前面子数组的和
    int n = nums.size();
    vector<int> dp(n + 1, 0);
    cout << dp[0];
    //int ret_max = -10000; //需要一个变量来记录返回的最大值
    int ret_max = INT_MIN;
    for (int i = 1; i <= n; ++i)
    {
        dp[i] = max(dp[i - 1] + nums[i - 1], nums[i - 1]);
        cout << dp[i] << " ";
        ret_max = max(ret_max, dp[i]);
    }
    return ret_max;

}



//https://leetcode.cn/problems/find-champion-i/submissions/522968064/?envType=daily-question&envId=2024-04-12
//2923. 找到冠军 I
int findChampion(vector<vector<int>>& grid)
{
    //因为 grid[i][i] != 0
    //就是找哪一行1最多就行 n-1
    int n = grid.size();
    for (int i = 0; i < n; ++i)
    {
        int sum = 0;
        for (int j = 0; j < n; ++j)
        {
            sum += grid[i][j];
        }
        if (sum == n - 1)
            return i;
    }
    return -1;
}



//https://leetcode.cn/problems/maximum-lcci/
//面试题 16.07. 最大数值

int maximum(int a, int b)
{
    long long ret = ((long long)a - (long long)b) >> 63;
    return ret == 0 ? a : b;
}



//https://leetcode.cn/problems/design-hashset/?envType=daily-question&envId=2024-04-14
//705. 设计哈希集合
class MyHashSet {
private:
    vector<int> hash_;
public:
    MyHashSet() : hash_(1e6 + 1)
    {}

    void add(int key)
    {
        if (hash_[key] == 0)
            hash_[key]++;
    }

    void remove(int key)
    {
        if (hash_[key] == 1)
            hash_[key]--;
    }

    bool contains(int key)
    {
        return hash_[key];
    }
};



//https://leetcode.cn/problems/find-majority-element-lcci/
//面试题 17.10. 主要元素
class Solution {
public:
    int majorityElement(vector<int>& nums)
    {
        //Boyer-Moore 投票算法
        int main_number = nums[0];
        int count = 0;
        for (auto& e : nums)
        {
            if (count == 0)
                main_number = e;

            if (e == main_number)
                count++;
            else
                count--;
        }
        //cout << main_number <<"  ";
        //此时记录下来的最多个数的元素 就是main_number
        //然后在判断是否超越一半
        count = 0;
        for (auto& e : nums)
        {
            if (e == main_number)
                count++;
        }

        return 2 * count > nums.size() ? main_number : -1;
    }

};


//https://leetcode.cn/problems/design-hashmap/description/
//706. 设计哈希映射
class MyHashMap {
private:
    vector<int> hash_;
public:
    MyHashMap() :hash_(1e6 + 1, -2)
    {}

    void put(int key, int value) {
        hash_[key] = value;
    }

    int get(int key) {
        return hash_[key] == -2 ? -1 : hash_[key];
    }

    void remove(int key) {
        hash_[key] = -2;
    }
};



//https://leetcode.cn/problems/sorted-merge-lcci/
//面试题 10.01. 合并排序的数组
void merge(vector<int>& A, int m, vector<int>& B, int n)
{
    for (int i = 0; i < n; ++i)
    {
        A[m + i] = B[i];
    }
    sort(A.begin(), A.end());
}


//https://leetcode.cn/problems/is-subsequence/description/
//392. 判断子序列
bool isSubsequence(string s, string t)
{
    if (s == "")
        return true;
    int n = t.size();
    int curs = 0; int curt = 0;
    while (curt < n)
    {
        if (s[curs] == t[curt])
        {
            curs++;
            if (curs == s.size())
                return true;
        }
        curt++;
    }
    return false;
}



//https://leetcode.cn/problems/smallest-difference-lcci/
//面试题 16.06. 最小差
int smallestDifference(vector<int>& a, vector<int>& b)
{
    sort(a.begin(), a.end());
    sort(b.begin(), b.end());

    int mindiff_pos = 0;
    int apos = 0; int bpos = 0;
    int mindiff = INT_MAX;
    while (apos < a.size() && bpos < b.size())
    {
        mindiff = min((long long)mindiff, abs((long long)a[apos] - (long long)b[bpos]));
        if (a[apos] < b[bpos])
        {
            ++apos;
        }
        else if (a[apos] > b[bpos])
        {
            ++bpos;
        }
        else
        {
            //如果两个相等
            return 0;
        }
    }
    return mindiff;
}




//https://leetcode.cn/problems/kth-node-from-end-of-list-lcci/description/
//面试题 02.02. 返回倒数第 k 个节点
int kthToLast(ListNode* head, int k)
{
    //用快慢指针
    ListNode* slow = head;
    ListNode* fast = head;
    while (k--)
        fast = fast->next;

    while (fast)
    {
        slow = slow->next;
        fast = fast->next;
    }

    return slow->val;

}

//https://leetcode.cn/problems/fan-zhuan-dan-ci-shun-xu-lcof/
//LCR 181. 字符串中的单词反转s
string reverseMessage(string message)
{
    int left, right;
    left = right = message.size() - 1;
    string rets;
    while (left >= 0)
    {
        if (message[left] != ' ')
        {
            right = left;
            //找到下一个left
            //!!!!注意 这里要left 在前 不然会越界访问！！
            while (left >= 0 && message[left] != ' ')
            {
                --left;
                cout << left << " ";
            }

            rets += message.substr(left + 1, right - left) + " ";

        }
        --left;
    }
    //cout<<rets.c_str()<<endl;
    //rets.pop_back();
    return rets.substr(0, rets.size() - 1);
}


//https://leetcode.cn/problems/find-original-array-from-doubled-array/?envType=daily-question&envId=2024-04-18
//2007. 从双倍数组中还原原数组
vector<int> findOriginalArray(vector<int>& changed)
{
    sort(changed.begin(), changed.end());
    unordered_map<int, int> hash;
    vector<int> retv;
    int n = changed.size();
    for (auto& e : changed)
        hash[e]++;

    for (int a : changed) {
        if (hash[a] == 0) {
            continue;
        }
        hash[a]--;
        if (hash[a * 2] == 0) {
            return {};
        }
        hash[a * 2]--;
        retv.push_back(a);
    }
    return retv;

}


//https://leetcode.cn/problems/ugly-number/
//263. 丑数
bool isUgly(int n)
{
    if (n == 0)
        return 0;
    //不断对 n / 2 3 5 最后如果是1说明是
    vector<int> arr = { 2, 3 ,5 };
    for (int i = 0; i < 3; ++i)
    {
        //比如 先判断能否被2整除 一直到不能除后 再除下一个数
        while (n % arr[i] == 0)
            n /= arr[i];

    }
    return n == 1;
}


//https://leetcode.cn/problems/ugly-number-ii/
//264. 丑数 II
int nthUglyNumber(int n)
{
    //用优先级队列 小堆
    //初始时堆为空。首先将最小的丑数 1 加入堆
    //每次取出堆顶元素 x，则 x 是堆中最小的丑数，由于2x, 3x, 5x 也是丑数，因此将 2x,3x,5x加入堆。
    //同时要注意去重 这样第n次拿出的就是n个丑数
    priority_queue<long, vector<long>, greater<long>> heap;
    unordered_set<long> s;

    //在搞一个数组来 方便判断遍历set
    vector<long> element = { 2, 3 ,5 };
    long ret = 0;
    heap.push(1);
    s.insert(1);
    for (int i = 0; i <= n; ++i)
    {
        for (auto& element_ : element)
        {
            if (s.count(element_ * ret) == 0)
            {
                heap.push(element_ * ret);
                s.insert(element_ * ret);
            }
        }
        ret = heap.top(); //此时拿到的是堆中的 最小丑数 ，其*2 *3 *5也是丑数
        heap.pop();
        //cout<< i<<":"<<ret<<endl;
    }
    return ret;
}


//https://leetcode.cn/problems/length-of-last-word/
//58. 最后一个单词的长度
int lengthOfLastWord(string s)
{
    int left = s.size() - 1;
    while (s[left] == ' ')
        --left;
    int right = left;
    while (left >= 0 && s[left] != ' ')
        --left;

    return right - left;
}



//https://leetcode.cn/problems/convert-sorted-array-to-binary-search-tree/description/
//108. 将有序数组转换为二叉搜索树
TreeNode* dfs(vector<int>& nums, int left, int right)
{
    if (left > right)
        return nullptr;

    //选择以中间的节点作为根节点
    int mid = left + (right - left) / 2;
    TreeNode* root = new TreeNode(nums[mid]);
    root->left = dfs(nums, left, mid - 1);
    root->right = dfs(nums, mid + 1, right);

    return root;
}

TreeNode* sortedArrayToBST(vector<int>& nums)
{
    TreeNode* root = nullptr;
    root = dfs(nums, 0, nums.size() - 1);

    return root;
}


//https://leetcode.cn/problems/minimum-depth-of-binary-tree/
//111. 二叉树的最小深度
class Solution {
public:
    void dfs(TreeNode* root, int height, int& min_height)
    {
        if (root == nullptr)
            return;


        if (root->left == nullptr && root->right == nullptr)
        {
            min_height = min(height, min_height);
            return;
        }

        height++;
        dfs(root->left, height, min_height);
        dfs(root->right, height, min_height);

    }

    int minDepth(TreeNode* root)
    {
        if (root == nullptr)
            return 0;
        int height = 1;
        int min_height = INT_MAX;
        dfs(root, height, min_height);
        return min_height;
    }
};


//https://leetcode.cn/problems/find-the-difference/
//389. 找不同
char findTheDifference(string s, string t)
{
    // unordered_map<char, int> hash;
    // for(auto& e : s)
    //     hash[e]++;

    // for(auto& e : t)
    // {
    //     if(hash.count(e) == 0)
    //         return e;
    // }
    // return ' ';

    //或者使用位运算  或者计数
    int ret = 0;
    for (auto e : s)
        ret ^= e;

    for (auto ch : t)
        ret ^= ch;

    return ret;

}



//https://leetcode.cn/problems/amount-of-time-for-binary-tree-to-be-infected/?envType=daily-question&envId=2024-04-24
//2385. 感染二叉树需要的总时间
class Solution {
private:
public:
    // int dfs(TreeNode* root, int& target, TreeNode*& start_root)
    // {
    //     if(root == nullptr)
    //         return 0;
    //     if(root->val == target)
    //         start_root = root;

    //     int left_hight = dfs(root->left, target, start_root);
    //     int right_hight = dfs(root->right, target, start_root);

    //     return left_hight > right_hight ?  left_hight+1 : right_hight+1;
    // }

    // int amountOfTime(TreeNode* root, int start) 
    // {
    //     TreeNode* start_root = nullptr;
    //     int height = dfs(root, start, start_root);
    //     cout<<height<<"  " << start_root->val << endl;

    //     int height2 = dfs(start_root, start, root);
    //     cout<<height2;

    //     return height + height2 - 2;
    // }


    int ans = 0;
    pair<int, bool> dfs(TreeNode* root, int& start)
    {
        if (root == nullptr)
        {
            return { 0, false };
        }

        auto [left_len, l_found] = dfs(root->left, start);
        auto [right_len, r_found] = dfs(root->right, start);

        if (root->val == start)
        {
            //计算子树的最大深度
            ans = max(left_len, right_len);
            return { 1, true };
        }

        if (l_found || r_found)
        {
            //只有在左子树或右子树包含 start时，才更新
            ans = max(ans, left_len + right_len);
            return { (l_found ? left_len : right_len) + 1, true };
        }
        return { max(left_len, right_len) + 1, false };
    }

    int amountOfTime(TreeNode* root, int start)
    {
        dfs(root, start);
        return ans;

    }
};


//https://leetcode.cn/problems/total-distance-traveled/submissions/527086063/?envType=daily-question&envId=2024-04-25
//2739. 总行驶距离
int distanceTraveled(int mainTank, int additionalTank)
{
    int MainL = 0;
    // if(mainTank < 5)
    //     return mainTank*10;
    while (mainTank >= 5)
    {
        mainTank -= 5;
        MainL += 5;
        if (additionalTank > 0)
        {
            mainTank++;
            additionalTank--;
        }
    }

    return MainL * 10 + mainTank * 10;
}



//https://leetcode.cn/problems/snapshot-array/?envType=daily-question&envId=2024-04-26
//1146. 快照数组
class SnapshotArray {
private:
    int snap_num_ = 0;
    vector< vector<pair<int, int> >> shotarr_; //建立一个二维
public:
    SnapshotArray(int length) :shotarr_(length)
    {}

    void set(int index, int val)
    {
        //这是之前错误的写法  只用了一维数组
        //shotarr_[index] = make_pair(snap_num_, val);
        shotarr_[index].push_back({ snap_num_, val });

    }

    int snap()
    {
        return snap_num_++;
    }

    int get(int index, int snap_id)
    {
        //二分
        // int left = 0; int right = shotarr_[index].size()-1;
        // int mid = -1;
        // while(left <= right)
        // {
        //     mid = left + (right - left)/2;
        //     if(shotarr_[index][mid].first > snap_id)
        //         right = mid-1;
        //     else
        //         left = mid+1;
        // }
        // cout<<mid<<endl;
        // cout<< shotarr_[index][mid].second<< endl;
        // return mid == -1? shotarr_[index][0].second : shotarr_[index][mid].second;

        //力扣官方题解
        auto x = upper_bound(shotarr_[index].begin(), shotarr_[index].end(), pair{ snap_id + 1, -1 });
        return x == shotarr_[index].begin() ? 0 : prev(x)->second;

    }

};


//https://leetcode.cn/problems/find-the-width-of-columns-of-a-grid/?envType=daily-question&envId=2024-04-27
//2639. 查询网格图中每一列的宽度
vector<int> findColumnWidth(vector<vector<int>>& grid)
{
    int m = grid.size();
    int n = grid[0].size();
    vector<int> retv(n);

    //一次遍历 从列开始 遍历每一列 并求出最大值
    for (int i = 0; i < n; ++i)
    {
        for (int j = 0; j < m; ++j)
            retv[i] = max(retv[i], (int)to_string(grid[j][i]).size());
    }
    return retv;
}


//https://leetcode.cn/problems/missing-number/
//268. 丢失的数字
int missingNumber(vector<int>& nums)
{
    //使用异或找不同 常规的想法
    int ret = 0;
    for (auto& num : nums)
        ret ^= num;

    for (int i = 0; i <= nums.size(); ++i)
        ret ^= i;

    return ret;
}


//https://leetcode.cn/problems/convert-to-base-2/?envType=daily-question&envId=2024-04-28
//1017. 负二进制转换
string baseNeg2(int n)
{
    if (n == 0)
        return "0";
    string rets;
    while (n)
    {
        int temp = n % (-2);
        n /= -2;
        if (temp == -1)
        {
            //遇到余数为-1的应该 把他修正为1计算原本是 -1 ÷ (-2) = 0 ... -1
            //                                      -1 ÷ (-2) = 1 ... 1
            // 修正余数为-1->1，对应商也要加1
            n++;
            temp = 1;
            //想错了 好像不是这样
            // rets.push_back('1');
            // rets.push_back('1');
        }

        rets.push_back(temp + '0');
        //cout<<temp+'0'<<" ";
    }
    reverse(rets.begin(), rets.end());
    return rets;
}



//https://leetcode.cn/problems/O4NDxx/
//LCR 013. 二维区域和检索 - 矩阵不可变
class NumMatrix {
private:
    vector<vector<long long>> dp;
public:
    void getdp(int m, int n)
    {
        vector<vector<long long>> arr(m, vector<long long>(n));
        dp = arr;
    }
    NumMatrix(vector<vector<int>>& matrix)
    {
        //dp[i][j]的值表示 从[1][1] 的位置到[i][j]位置 这一段区间里所有元素的和
        int m = matrix.size();
        int n = matrix[0].size();
        //dp(m+1, vector<int>(n+1)); //因为下表是从1开始的  这样初始化是错的
        //getdp(m+1, n+1); //方法1
        dp.resize(m + 1, vector<long long>(n + 1)); //方法二

        //建立前缀和数组
        for (int i = 1; i <= m; ++i)
        {
            for (int j = 1; j <= n; ++j)
                dp[i][j] = dp[i - 1][j] + dp[i][j - 1] + matrix[i - 1][j - 1] - dp[i - 1][j - 1];
        }
    }

    int sumRegion(int row1, int col1, int row2, int col2)
    {
        //使用前缀和矩阵
        return dp[row2 + 1][col2 + 1] - dp[row1 - 1 + 1][col2 + 1] - dp[row2 + 1][col1 - 1 + 1] + dp[row1 - 1 + 1][col1 - 1 + 1];
    }
};


//https://leetcode.cn/problems/tvdfij/submissions/527997240/
//LCR 012. 寻找数组的中心下标
int pivotIndex(vector<int>& nums)
{
    //前缀和数组
    int n = nums.size();
    vector<int> f(n);
    auto g(f);

    //i表示[0,i-1]区间内的 所有元素的和
    for (int i = 1; i < n; ++i)
        f[i] = f[i - 1] + nums[i - 1];

    for (int i = n - 2; i >= 0; --i)
        g[i] = g[i + 1] + nums[i + 1];

    for (int i = 0; i < n; ++i)
        if (f[i] == g[i])
            return i;

    return -1;
}


//https://leetcode.cn/problems/number-of-employees-who-met-the-target/?envType=daily-question&envId=2024-04-30
//2798. 满足目标工作时长的员工数目
int numberOfEmployeesWhoMetTarget(vector<int>& hours, int target)
{
    int count = 0;
    for (int i = 0; i < hours.size(); ++i)
        if (hours[i] >= target)
            count++;
    return count;

}


// https://leetcode.cn/problems/number-of-1-bits/description/
//191. 位1的个数
int hammingWeight(int n)
{
    int count = 0;
    while (n)
    {
        n &= n - 1;
        count++;
    }
    return count;
}


//https://leetcode.cn/problems/contains-duplicate/
//217. 存在重复元素
bool containsDuplicate(vector<int>& nums)
{
    unordered_set<int> hash;
    for (auto& num : nums)
    {
        if (hash.count(num) == 1)
            return true;
        hash.insert(num);
    }
    return false;
}


//https://leetcode.cn/problems/sum-of-left-leaves/
//404. 左叶子之和
class Solution {
public:
    void dfs(TreeNode* root, bool isleft, int& sum)
    {
        if (root == nullptr)
            return;
        if (root->left == nullptr && root->right == nullptr && isleft)
            sum += root->val;
        dfs(root->left, true, sum);
        dfs(root->right, false, sum);

    }
    int sumOfLeftLeaves(TreeNode* root) {
        int sum = 0;
        dfs(root, false, sum);
        return sum;
    }
};


//https://leetcode.cn/problems/average-salary-excluding-the-minimum-and-maximum-salary/?envType=daily-question&envId=2024-05-03
//1491. 去掉最低工资和最高工资后的工资平均值
double average(vector<int>& salary)
{
    double sum = 0;
    int min_s = INT_MAX; int max_s = INT_MIN;
    for (auto& num : salary)
    {
        min_s = min(min_s, num);
        max_s = max(max_s, num);
        sum += num;
    }
    return (sum - min_s - max_s) / (salary.size() - 2);
}


//https://leetcode.cn/problems/reverse-linked-list-ii/
//92. 反转链表 II
class Solution {
public:
    // ListNode* reverseBetween(ListNode* head, int left, int right) 
    // {
    //     if(head->next == nullptr || left == right)
    //         return head;
    //     ListNode* phead = new ListNode(-1, head);
    //     ListNode* newhead = nullptr;
    //     ListNode* left_pre = phead;
    //     ListNode* cur = head;

    //     while(--left)
    //     {
    //         left_pre = cur;
    //         cur = cur->next;
    //     }

    //     ListNode* right_next = cur;

    //     // if(cur != nullptr)
    //     //     cout<< cur->val <<" " <<left_pre->val<<" ";
    //     int n = right - left;
    //     while(--n)
    //     {

    //         ListNode* next = cur->next;
    //         cur->next = newhead;
    //         newhead = cur;
    //         cur = next;
    //     }
    //     //cout<< cur->val <<endl;
    //     // ListNode*cur1 = newhead;
    //     // while(cur1)
    //     // {
    //     //     cout<< cur1->val<<" ";
    //     //     cur1 = cur1->next;
    //     // }
    //     left_pre->next = nullptr;
    //     right_next->next = nullptr;

    //     left_pre->next = newhead;
    //     right_next->next = cur;

    //     // ListNode* cur1 = phead;
    //     // while(cur1)
    //     // {
    //     //     cout<< cur1->val<<" ";
    //     //     cur1 = cur1->next;
    //     // }

    //     return phead->next;
    // }
    ListNode* reverseBetween(ListNode* head, int left, int right)
    {
        ListNode* phead = new ListNode(-1);
        phead->next = head;
        ListNode* left_pre = phead;

        //先找到左边要连接的节点
        for (int i = 0; i < left - 1; ++i)
        {
            left_pre = left_pre->next;
        }
        // cout << left_pre->val;
        //再走 right-left+1 找到 right_next节点
        ListNode* right_next = left_pre;
        int n = right - left + 1;
        for (int i = 0; i < n; ++i)
        {
            //或者就是先切断一段出来再逆置 不会那么绕
            right_next = right_next->next;
            cout << right_next->val << " ";

        }

        ListNode* leftNode = left_pre->next;
        //来一个记录 right_next 的下一个值
        ListNode* rightNode = right_next->next;

        // //切断
        left_pre->next = nullptr;
        right_next->next = nullptr;

        //反转链表
        ListNode* newhead = nullptr;
        ListNode* cur = leftNode;
        while (cur)
        {
            ListNode* next = cur->next;
            cur->next = newhead;
            newhead = cur;
            cur = next;
        }

        //连接回原链表
        left_pre->next = newhead;
        leftNode->next = rightNode;

        return phead->next;
    }

};


//https://leetcode.cn/problems/product-of-array-except-self/submissions/529067432/
//除自身以外数组的乘积
vector<int> productExceptSelf(vector<int>& nums)
{
    //求一个 i位置的 先求出0 - i-1的前缀乘积，在求出i+1到n-1的 后缀乘积
    int n = nums.size();
    vector<int> f(n);
    auto g(f);

    f[0] = 1;
    for (int i = 1; i < n; ++i)
    {
        f[i] = f[i - 1] * nums[i - 1];
    }
    g[n - 1] = 1;
    for (int i = n - 2; i >= 0; --i)
    {
        g[i] = g[i + 1] * nums[i + 1];
    }

    vector<int> retv;
    for (int i = 0; i < n; ++i)
    {
        retv.push_back(f[i] * g[i]);
    }

    return retv;
}


//https://leetcode.cn/problems/subarray-sum-equals-k/
//560. 和为 K 的子数组
int subarraySum(vector<int>& nums, int k)
{
    //知道以i为结尾的前缀和的数后，只要求除[0, i-1]之间有多少的前缀和等于 sum[i]-k
    unordered_map<int, int> hash;
    int sum = 0; int ret = 0;
    hash[0] = 1;
    for (auto& e : nums)
    {
        sum += e;
        if (hash.count(sum - k))
        {
            ret += hash[sum - k];
        }
        hash[sum]++;
    }
    return ret;

}



//https://leetcode.cn/problems/defuse-the-bomb/submissions/529284383/?envType=daily-question&envId=2024-05-05
//1652. 拆炸弹
vector<int> decrypt(vector<int>& code, int k)
{
    int n = code.size();
    vector<int> retv(n);
    if (k == 0)
        return retv;
    if (k > 0)
    {
        for (int i = 0; i < n; ++i)
        {
            int sum = 0;
            int j = i + 1;
            int times = k;
            while (times--)
            {
                j %= n;
                sum += code[j];
                j++;
            }
            retv[i] = sum;
        }
    }
    if (k < 0)
    {
        for (int i = 0; i < n; ++i)
        {
            int sum = 0;
            int j = i + (n + k);
            int times = -k;
            cout << j << " ";
            while (times--)
            {
                j %= n;
                sum += code[j];
                j++;
            }
            retv[i] = sum;
        }
    }

    return retv;
}



//https://leetcode.cn/problems/is-unique-lcci/
//面试题 01.01. 判定字符是否唯一
bool isUnique(string astr) {
    unordered_set<char> hash;
    for (auto& ch : astr)
    {
        auto p = hash.insert(ch);
        if (p.second == false)
            return false;
    }
    return true;
}



//https://leetcode.cn/problems/subarray-sums-divisible-by-k/
//974. 和可被 K 整除的子数组
int subarraysDivByK(vector<int>& nums, int k)
{
    //在 [0, 1]区间内，找到有多少个前缀和的余数等于  同余数定理
    unordered_map<int, int> hash;
    int sum = 0; int ret = 0;
    hash[0 % k] = 1;
    for (auto& e : nums)
    {
        //先算出当前的前缀和
        sum += e;
        int r = (sum % k + k) % k; //修正后的余数
        if (hash.count(r))
            ret += hash[r]; //统计余数个数
        hash[r]++;
    }
    return ret;



}



//https://leetcode.cn/problems/watering-plants/?envType=daily-question&envId=2024-05-08
//2079. 给植物浇水
int wateringPlants(vector<int>& plants, int capacity)
{
    int step = 0; int cap = capacity;
    int n = plants.size();
    for (int i = 0; i < n; )
    {
        if (cap >= plants[i])
        {
            step++;
            cap -= plants[i];
            i++;
        }
        else
        {
            step += i * 2;
            cap = capacity;
        }
    }
    return step;

}


//https://leetcode.cn/problems/watering-plants-ii/?envType=daily-question&envId=2024-05-09
//2105. 给植物浇水 II
int minimumRefill(vector<int>& plants, int capacityA, int capacityB)
{
    int times = 0; int n = plants.size();
    int left = 0; int right = n - 1;
    int capA = capacityA; int capB = capacityB;
    while (left <= right)
    {
        if (left == right)
        {
            if (capA < plants[left] && capB < plants[right])
            {
                times++;
                //cout<<"times"<<left<<" ";
                break;
            }
            break;
        }

        if (capA >= plants[left])
        {
            capA -= plants[left];
            left++;
            //cout << capA <<" ";
            //cout << "left:" << left <<" " <<endl;
        }
        else
        {
            capA = capacityA;
            capA -= plants[left];
            times++;
            left++;
        }

        if (capB >= plants[right])
        {
            capB -= plants[right];
            right--;
            //cout << capB <<" ";
            //cout << "right:" << right << " "<<endl;
        }
        else
        {
            capB = capacityB;
            capB -= plants[right];
            times++;
            right--;
        }
        //cout << "times:" << time <<" ";

    }
    return times;
}


//https://leetcode.cn/problems/count-tested-devices-after-test-operations/submissions/530726976/?envType=daily-question&envId=2024-05-10
//2960. 统计已测试设备
int countTestedDevices(vector<int>& batteryPercentages)
{
    int count = 0;
    for (int i = 0; i < batteryPercentages.size(); ++i)
    {
        batteryPercentages[i] -= count;
        if (batteryPercentages[i] > 0)
            count++;
    }
    return count;

}


//https://leetcode.cn/problems/minimum-amount-of-time-to-collect-garbage/?envType=daily-question&envId=2024-05-11
//2391. 收集垃圾的最少总时间
int garbageCollection(vector<string>& garbage, vector<int>& travel)
{
    int n = garbage.size(); int m = travel.size();
    int M_time = 0; int P_time = 0; int G_time = 0;
    int M_pos = 0; int P_pos = 0; int G_pos = 0;
    for (int i = 0; i < n; ++i)
    {
        // if(garbage[i].find("G") != string::npos)
        // {
        //     G_pos = i;
        // }
        // if(garbage[i].find('P') != string::npos)
        // {
        //     P_pos = i;

        // }
        // if(garbage[i].find('M') != string::npos)
        // {
        //     M_pos = i;
        // }

        for (auto& ch : garbage[i])
        {
            if (ch == 'G')
            {
                G_pos = i;
                G_time++;
            }
            if (ch == 'M')
            {
                M_pos = i;
                M_time++;
            }
            if (ch == 'P')
            {
                P_pos = i;
                P_time++;
            }
        }
        cout << garbage[i].c_str() << endl;
    }
    cout << "G_time:" << G_time << " M_time:" << M_time << " P_time:" << P_time << endl;
    cout << "G_pos:" << G_pos << " M_pos:" << M_pos << " P_pos:" << P_pos << endl;
    //再看一下MPG最远能到哪里
    vector<int> sum(m + 1, 0);
    sum[0] = 0;
    for (int i = 1; i <= m; ++i)
        sum[i] = sum[i - 1] + travel[i - 1];

    for (auto e : sum)
        cout << e << " ";

    int time = G_time + M_time + P_time + sum[G_pos] + sum[P_pos] + sum[M_pos];
    //int time = 0;
    return time;

}


//https://leetcode.cn/problems/contiguous-array/
//525. 连续数组
int findMaxLength(vector<int>& nums)
{
    //前缀和 如果把0改成-1,那么不就是求最小和为0的子数组
    //一个存前缀和  一个存 长度
    unordered_map<int, int> hash;
    for (auto& e : nums)
    {
        if (e == 0)
            e = -1;
    }
    hash[0] = -1;

    int sum = 0; int max_l = 0;
    for (int i = 0; i < nums.size(); ++i)
    {
        sum += nums[i];
        if (hash.count(sum))
        {
            max_l = max(max_l, i - hash[sum]);
        }
        else
            hash[sum] = i;
    }
    return max_l;

}


//https://leetcode.cn/problems/counting-bits/
//338. 比特位计数
vector<int> countBits(int n) {
    vector<int> ret;
    for (int i = 0; i <= n; ++i)
    {
        int temp = i;
        int count = 0;
        while (temp)
        {
            temp &= temp - 1;
            count++;
        }
        ret.push_back(count);
    }
    return ret;
}


//https://leetcode.cn/problems/hamming-distance/
//461. 汉明距离
int hammingDistance(int x, int y) {
    //二进制不同位的个数
    int temp = x ^ y;
    int count = 0;
    while (temp)
    {
        count += temp & 1;
        temp >>= 1;
    }
    return count;
}


//https://leetcode.cn/problems/is-unique-lcci/
// 面试题 01.01. 判定字符是否唯一
//用位图思想
bool isUnique(string astr) {
    //用一个 int 变量来表示  用 0-25位来表示 26个字母
    if (astr.size() > 26)
        return false;
    int bitmap = 0;
    for (auto ch : astr)
    {
        //先找一下 是不是已经存在了
        int i = ch - 'a';
        if ((bitmap >> i) & 1 == 1)
            return false;
        //可以把当前字符加入到位图中
        bitmap |= (1 << i);
    }
    return true;
}



//https://leetcode.cn/problems/rotting-oranges/?envType=daily-question&envId=2024-05-13
//994. 腐烂的橘子
//看答案的 不会做
class Solution {
public:
    int dis[10][10];

    int orangesRotting(vector<vector<int>>& grid)
    {
        queue<pair<int, int>> q;
        vector<int> dir_x = { 0, 1, 0, -1 };
        vector<int> dir_y = { 1, 0, -1, 0 };
        memset(dis, -1, sizeof(dis)); //初始化为-1 刚好是分钟
        int count = 0;

        int m = grid.size(); int n = grid[0].size();
        for (int i = 0; i < m; ++i)
        {
            for (int j = 0; j < n; ++j)
            {
                if (grid[i][j] == 2)
                {
                    q.push({ i, j });
                    cout << "i:" << i << " j:" << j << endl;
                    dis[i][j] = 0;
                }
                else if (grid[i][j] == 1)
                {
                    //统计新鲜橘子个数
                    ++count;
                }
            }
        }
        int ret = 0;
        while (!q.empty())
        {
            //把腐烂橘子剥离，同时判断四个方向上有无新鲜橘子，如果有就进入队列，说明是下一个要腐烂的
            auto pos = q.front();
            q.pop();
            int i = pos.first; int j = pos.second;
            //遍历四个方位
            for (int k = 0; k < 4; ++k)
            {
                int x = i + dir_x[k];
                int y = j + dir_y[k];
                //判断边界 以及是否有新鲜橘子                                或者已经是腐烂的橘子了
                if (x < 0 || x >= m || y < 0 || y >= n || grid[x][y] == 0 || dis[x][y] != -1)
                    continue;

                dis[x][y] = dis[i][j] + 1;
                q.push({ x, y });
                if (grid[x][y] == 1)
                {
                    //如果是新鲜橘子
                    count -= 1;
                    ret = dis[x][y];
                    if (!count)
                        break;
                }

            }
        }
        cout << count << endl;
        return count > 0 ? -1 : ret;
    }
};


//https://leetcode.cn/problems/sum-of-two-integers/
//371. 两整数之和
int getSum(int a, int b)
{
    //异或 异或操作就是 不进位的相加
    //所以可以先求出 不进位相加，再看一下那些bit位需要进位
    while (b)
    {
        uint32_t carry = (uint32_t)(a & b) << 1;
        a = a ^ b;
        b = carry;
        cout << a << "  " << b << endl;
    }
    return a;

}


//https://leetcode.cn/problems/minimum-rounds-to-complete-all-tasks/?envType=daily-question&envId=2024-05-14
//2244. 完成所有任务需要的最少轮数

int minimumRounds(vector<int>& tasks)
{
    unordered_map<int, int> hash;
    int sum = 0;
    for (auto e : tasks)
    {
        hash[e]++;
    }

    for (auto it = hash.begin(); it != hash.end(); ++it)
    {
        if (it->second < 2)
            return -1;
        //看这个数能被几个 3 整除，说明有 n/3个 如果余下来 1 或者 2 说明 最后只能通过两个 2 来结束
        if (it->second % 3 == 0)
        {
            sum += it->second / 3;
        }
        else if (it->second % 3 == 1 || it->second % 3 == 2)
        {
            sum += it->second / 3 + 1;
        }

    }
    return sum;
}


class Solution {
public:
    int sum(int num1, int num2) {
        return num1 + num2;
    }
};



//https://leetcode.cn/problems/maximum-number-of-weeks-for-which-you-can-work/
//1953. 你可以工作的最大周数
long long numberOfWeeks(vector<int>& milestones)
{
    //和 2244.完成所有任务需要的最少轮数
    //https://leetcode.cn/problems/minimum-rounds-to-complete-all-tasks/description/?envType=daily-question&envId=2024-05-14
    long long max_num = 0;
    long long sum = 0; //剩下的
    for (int i = 0; i < milestones.size(); ++i)
    {
        max_num = max((long long)milestones[i], max_num);
        sum += milestones[i];
    }
    sum -= max_num;

    if (max_num > sum + 1)
    {
        return sum * 2 + 1;
    }
    else
    {
        return max_num + sum;
    }

}



//https://leetcode.cn/problems/most-profit-assigning-work/?envType=daily-question&envId=2024-05-17
//826. 安排工作以达到最大收益
int maxProfitAssignment(vector<int>& difficulty, vector<int>& profit, vector<int>& worker)
{
    sort(worker.begin(), worker.end());
    vector<pair<int, int>> hash;
    for (int i = 0; i < difficulty.size(); ++i)
        hash.push_back({ difficulty[i], profit[i] });

    sort(hash.begin(), hash.end());
    // for(auto e: hash)
    // {
    //     cout<<e.first<<" "<<e.second<<endl;
    // }
    //双指针
    int sum = 0; int max_profit = 0;
    //cout<<worker.size()<<endl;
    for (int hi = 0, wi = 0; wi < worker.size(); )
    {
        while (hi < hash.size() && worker[wi] >= hash[hi].first)
        {
            max_profit = max(max_profit, hash[hi].second);
            ++hi;
        }
        sum += max_profit;
        ++wi;
    }

    return sum;

}



//https://leetcode.cn/problems/find-the-maximum-divisibility-score/?envType=daily-question&envId=2024-05-18
//2644. 找出可整除性得分最大的整数
int maxDivScore(vector<int>& nums, vector<int>& divisors)
{
    int n = nums.size(); int m = divisors.size();
    pair<int, int> max_div = { -1, -1 };
    for (int i = 0; i < m; ++i)
    {
        int count = 0;
        for (int j = 0; j < n; ++j)
        {
            if (nums[j] % divisors[i] == 0)
                count++;
        }

        if (count > max_div.second || (count == max_div.second && divisors[i] < max_div.first))
        {
            max_div.first = divisors[i];
            max_div.second = count;
        }
    }
    return max_div.first;

}



//https://leetcode.cn/problems/find-the-winner-of-an-array-game/?envType=daily-question&envId=2024-05-19
//1535. 找出数组游戏的赢家
int getWinner(vector<int>& arr, int k)
{
    //如果比较后放到最后面，第一个数肯定是比最后面的数要大的 所以只要走一次就可以了
    int winner = max(arr[0], arr[1]);
    if (k == 1)
        return winner;

    int cnt = 1;
    for (int i = 2; i < arr.size(); ++i)
    {
        if (winner > arr[i])
        {
            cnt++;
            if (cnt == k)
                return winner;
        }
        else
        {
            cnt = 1;
            winner = arr[i];
        }
    }
    return winner;

}


bool validUtf8(vector<int>& data)
{
    int man = 0;
    if (data.size() == 1)
    {
        if (((data[0] >> 7) & 1) == 0)
            return true;
        else
            return false;
    }

    for (int i = 0; i < data.size(); )
    {
        int cnt = 0;
        if (i + 1 == data.size())
        {
            if (((data[i] >> 7) & 1) == 0)
                return true;
            else
                return false;
        }

        for (int j = 0; j < 8; ++j)
        {
            if ((data[i] >> (7 - j)) & 1 == 1)
                cnt++;
            else
                break;
        }
        cout << cnt << endl;
        i++;

        if (cnt == 1)
        {

        }

        while (--cnt && i < data.size())
        {
            data[i] &= 0b11000000;
            if (data[i] ^ 0b10000000 == 0)
                i++;
            else
                return false;
        }
        man = cnt;
    }
    return man > 0 ? false : true;
}


//https://leetcode.cn/problems/find-the-maximum-achievable-number/
//2769. 找出最大的可达成数字
class Solution {
public:
    int theMaximumAchievableX(int num, int t)
    {
        return num + 2 * t;
    }
};



//https://leetcode.cn/problems/find-players-with-zero-or-one-losses/
//2225. 找出输掉零场或一场比赛的玩家
vector<vector<int>> findWinners(vector<vector<int>>& matches)
{
    // unordered_map<int, pair<int, int>> hash;
    map<int, pair<int, int>> hash;

    for (auto& match : matches)
    {
        hash[match[0]].first++;
        hash[match[1]].second++;
    }
    for (auto& e : hash)
    {
        cout << e.first << ":{" << e.second.first << "," << e.second.second << "}" << endl;
    }

    vector<vector<int>> retv(2, vector<int>(0));
    for (auto e : hash)
    {
        if (e.second.second == 0)
        {
            retv[0].push_back(e.first);
        }

        if (e.second.second == 1)
        {
            retv[1].push_back(e.first);
        }
    }
    return retv;
}


//https://leetcode.cn/problems/WGki4K/
//LCR 004. 只出现一次的数字 II
int singleNumber(vector<int>& nums)
{
    //除了用hash表 还可以用位运算
    int ret = 0;
    for (int i = 0; i < 32; ++i)
    {
        int sum = 0;
        for (auto& num : nums)
        {
            sum += ((num >> i) & 1);
        }
        //算出的值和 单独的那一个数的哪一位是一样的
        ret |= ((sum % 3) << i);
    }
    return ret;

}



//2831. 找出最长等值子数组
//https://leetcode.cn/problems/find-the-longest-equal-subarray/?envType=daily-question&envId=2024-05-23
int longestEqualSubarray(vector<int>& nums, int k)
{
    int n = nums.size();
    //记录每一个元素的下标的位置
    unordered_map<int, vector<int>> hash_pos;
    for (int i = 0; i < n; ++i)
    {
        hash_pos[nums[i]].push_back(i);
    }

    // for(auto e : hash_pos)
    // {
    //     cout << e.first << ":";
    //     for(auto arr : e.second)
    //     {
    //         cout << arr << " ";
    //     }
    //     cout << endl;
    // }

    //滑动窗口 那么hash中存的下表 {1, 3 ,5} 说明子数组 1-3 中 只有2下标不是相同的数
    int ret = 0;
    for (auto e : hash_pos)
    {
        for (int left = 0, right = 0; right < e.second.size(); ++right)
        {
            //判断区间中要删除的元素的个数 大于K了就left右移   该相同元素出现的次数
            //int del = e.second[right] - e.second[left] - (right - left);
            //cout <<"num:"<<e.first <<" del:" << del <<endl;
            while (e.second[right] - e.second[left] - (right - left) > k)
            {
                ++left;
            }
            // //这里如果 等于退出条件了 得回一下
            // if(right == e.second.size())
            // {
            //     --right;
            //     ret = max(ret, right - left + 1);
            //     break;
            // }
            ret = max(ret, right - left + 1);
        }
    }
    return ret;
}



//https://leetcode.cn/problems/contains-duplicate-ii/
//219. 存在重复元素 II
bool containsNearbyDuplicate(vector<int>& nums, int k) {
    unordered_map<int, vector<int>> hash;
    for (int i = 0; i < nums.size(); ++i)
    {
        hash[nums[i]].push_back(i);
    }

    for (auto& arr : hash)
    {
        for (int i = 0; i < arr.second.size(); ++i)
        {
            for (int j = i + 1; j < arr.second.size(); ++j)
            {
                if (arr.second[j] - arr.second[i] <= k)
                {
                    return true;
                }
            }
        }
    }
    return false;
}


<<<<<<< HEAD
//https://leetcode.cn/problems/find-missing-observations/?envType=daily-question&envId=2024-05-27
//2028. 找出缺失的观测数据
vector<int> missingRolls(vector<int>& rolls, int mean, int n)
{
    vector<int> ret;
    int m = rolls.size();
    int sum = mean * (m + n);
    int rsum = 0;
    for (auto& e : rolls)
        rsum += e;
    int gap = sum - rsum;
    if (gap < n || gap > 6 * n)
        return {};

    int missnum = gap / n;
    //余数 也要算一下
    int remainder = gap % n; int temp = 0;
    for (int i = 0; i < n; ++i)
    {
        if (remainder > 0)
        {
            ret.push_back(missnum + 1);
            remainder--;
        }
        else
            ret.push_back(missnum);
    }

    return ret;

}
=======
//https://leetcode.cn/problems/find-indices-with-index-and-value-difference-i/?envType=daily-question&envId=2024-05-25
//2903. 找出满足差值条件的下标 I
vector<int> findIndices(vector<int>& nums, int indexDifference, int valueDifference)
{
    for (int i = 0; i < nums.size(); ++i)
    {
        for (int j = i + indexDifference; j < nums.size(); ++j)
        {
            if (abs(nums[i] - nums[j]) >= valueDifference)
                return { i, j };
        }
    }
    return { -1, -1 };
}
//     int n = nums.size();
//     //找一个最小的i  最大的j
//     int min_i = INT_MAX; int max_j = 0;
//     for(int j = indexDifference; j < n; ++j)
//     {
//         int i = j - indexDifference;
//         if(nums[i] < min_i)
//         {
//             min_i = i;
//         }


//         cout << min_i <<" "<<max_j <<endl;
//         if(abs(nums[min_i] - nums[max_j]) >= valueDifference)
//         {
//             return {min_i, max_j};
//         }
//     }
//     return {-1, -1};    
// }



//https://leetcode.cn/problems/find-kth-largest-xor-coordinate-value/?envType=daily-question&envId=2024-05-26
//1738. 找出第 K 大的异或坐标值
int kthLargestValue(vector<vector<int>>& matrix, int k) {
    //二维前缀和
    int m = matrix.size();
    int n = matrix[0].size();
    vector<vector<int>> pre(m + 1, vector<int>(n + 1));
    //或者这里用 优先级队列 
    priority_queue<int> q;
    vector<int> ret;
    for (int i = 1; i < m + 1; ++i)
    {
        for (int j = 1; j < n + 1; ++j)
        {
            pre[i][j] = pre[i - 1][j - 1] ^ pre[i - 1][j] ^ pre[i][j - 1] ^ matrix[i - 1][j - 1];
            q.push(pre[i][j]);
        }
    }

    //sort
    //sort(ret.begin(), ret.end(), greater<int>());
    // while(!q.empty())
    // {
    //     int top = q.top();
    //     cout << top <<" ";
    //     q.pop();
    // }
    while (--k)
        q.pop();
    return q.top();
}
>>>>>>> abaabb26c7504ba7b5d3ac463e08eeda2370f1a4



//https://leetcode.cn/problems/find-the-peaks/?envType=daily-question&envId=2024-05-28
//2951. 找出峰值
vector<int> findPeaks(vector<int>& mountain) {
    vector<int> ret;
    int n = mountain.size();
    for (int i = 1; i < n - 1; ++i)
    {
        if (mountain[i] > mountain[i - 1] && mountain[i + 1] < mountain[i])
            ret.push_back(i);
    }
    return ret;
}



//https://leetcode.cn/problems/path-sum/
//112. 路径总和
bool dfs(TreeNode* root, int& targetSum, int sum)
{
    if (!root)
        return false;

    sum += root->val;
    if (!root->left && !root->right)
    {
        if (sum == targetSum)
            return true;
        else
            return false;
    }
    return dfs(root->left, targetSum, sum) || dfs(root->right, targetSum, sum);
}

bool hasPathSum(TreeNode* root, int targetSum)
{
    int sum = 0;
    return dfs(root, targetSum, sum);

}


//https://leetcode.cn/problems/maximum-number-of-balloons/
//1189. “气球” 的最大数量
class Solution {
public:
    int maxNumberOfBalloons(string text)
    {
        vector<int> balloon(30);
        for (auto& e : text)
        {
            if (e == 'b' || e == 'a' || e == 'l' || e == 'o' || e == 'n')
                balloon[e - 'a']++;
        }
        balloon['l' - 'a'] /= 2;
        balloon['o' - 'a'] /= 2;
        //找出最小值
        return (int)min({ balloon['a' - 'a'], balloon['b' - 'a'], balloon['l' - 'a'], balloon['o' - 'a'], balloon['n' - 'a'] });
        //return *min_element(balloon.begin(), balloon.end());
    }
};



//https://leetcode.cn/problems/second-minimum-node-in-a-binary-tree/
//671. 二叉树中第二小的节点
void dfs(TreeNode* root, int& ret, int& rootval)
{
    if (!root)
        return;

    if (ret != -1 && root->val >= ret)
        return;

    if (root->val > rootval)
    {
        ret = root->val;
    }


    dfs(root->left, ret, rootval);
    dfs(root->right, ret, rootval);
}
int findSecondMinimumValue(TreeNode* root) {
    int ret = -1;
    int rootval = root->val;
    dfs(root->left, ret, rootval);
    dfs(root->right, ret, rootval);

    return ret;

}


//https://leetcode.cn/problems/find-missing-and-repeated-values/description/?envType=daily-question&envId=2024-05-31
//2965. 找出缺失和重复的数字
vector<int> findMissingAndRepeatedValues(vector<vector<int>>& grid)
{
    int n = grid.size();
    vector<int> count(n * n + 1);
    vector<int> ret(2);

    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < n; j++)
        {
            count[grid[i][j]]++;
        }
    }

    for (int i = 0; i <= n * n; ++i)
    {
        if (count[i] == 2)
            ret[0] = i;
        if (count[i] == 0)
            ret[1] = i;
    }

    return ret;
}


//374. 猜数字大小
//https://leetcode.cn/problems/guess-number-higher-or-lower/submissions/536303301/
int guessNumber(int n) {
    int left = 0; int right = n;
    while (left < right)
    {
        int mid = left + (right - left) / 2;
        if (guess(mid) <= 0)
            right = mid;
        else
            left = mid + 1;
    }
    return left;

}


//https://leetcode.cn/problems/distribute-candies-among-children-i/description/?envType=daily-question&envId=2024-06-01
//2928. 给小朋友们分糖果 I
int distributeCandies(int n, int limit)
{
    int ret = 0;
    for (int i = 0; i <= limit; ++i)
    {
        for (int j = 0; j <= limit; ++j)
        {
            if (i + j > n)
            {
                break;
            }
            if (n - (i + j) <= limit)
            {
                ret++;
            }
        }
    }
    return ret;


}


//https://leetcode.cn/problems/distribute-candies/?envType=daily-question&envId=2024-06-02
//575. 分糖果
int distributeCandies(vector<int>& candyType)
{
    int n = candyType.size();
    int count = 0;
    unordered_set<int> set;
    for (auto& e : candyType)
    {
        if (set.count(e) == 0)
        {
            set.insert(e);
            count++;
        }
    }
    return min(count, n / 2);


}


//https://leetcode.cn/problems/distribute-candies-to-people/?envType=daily-question&envId=2024-06-03
//1103. 分糖果 II
vector<int> distributeCandies(int candies, int num_people)
{
    int i = 0; int candy = 1;
    vector<int> retv(num_people);
    while (candies > 0)
    {
        i %= num_people;
        retv[i++] += min(candies, candy);
        candies -= candy;
        candy++;
    }
    return retv;
}


//https://leetcode.cn/problems/sum-root-to-leaf-numbers/?envType=study-plan-v2&envId=top-interview-150
//129. 求根节点到叶节点数字之和
void dfs(TreeNode* root, int num, int& sum)
{
    if (root == nullptr)
        return;

    num = num * 10 + root->val;
    if (root->left == nullptr && root->right == nullptr)
        sum += num;

    dfs(root->left, num, sum);
    dfs(root->right, num, sum);
}
int sumNumbers(TreeNode* root)
{
    int sum = 0; int num = 0;
    dfs(root, num, sum);
    return sum;
}




//290. 单词规律
//https://leetcode.cn/problems/word-pattern/?envType=study-plan-v2&envId=top-interview-150
// bool wordPattern(string pattern, string s) 
// {
//     vector<string> hash(100, "-1");
//     unordered_map<string, char> hash2;
//     s += " ";
//     int start = 0;
//     for(int i = 0; i < pattern.size(); ++i)
//     {
//         if(hash[pattern[i]] == "-1")
//         {
//             int pos = s.find(" ", start);
//             if(pos != std::string::npos)
//             {
//                 hash[pattern[i]] = s.substr(start, pos - start);
//                 start = pos + 1;
//                 hash2[s.substr(start, pos - start)] = pattern[i];
//             }
//             cout<< s.substr(start, pos - start) << " ";
//         }
//         else
//         {
//             int pos = s.find(" ", start);
//             if(pos != std::string::npos)
//             {
//                 string sub = s.substr(start, pos - start);
//                 if(hash2[sub] != pattern[i])
//                 {

//                 }

//                 if(hash2[s.substr(start, pos - start)] != pattern[i])
//                     return false;
//             }
//             start = pos + 1;
//             cout<< s.substr(start, pos - start) << " ";
//         }

//     }
//     return true;
// }
bool wordPattern(string pattern, string s) {
    string word = "";
    //映射表
    unordered_map<char, string> mp;
    //被映射表
    unordered_map<string, char> mpe;

    int i = 0, j = 0;
    for (i = 0, j = 0; i < pattern.size(); ++i)
    {
        if (j >= s.length() && i < pattern.size())
            return false;

        while (s[j] != ' ' && j < s.length())
        {
            word.push_back(s[j]);
            ++j;
        }
        if (mp.count(pattern[i]))
        {
            if (mp[pattern[i]] != word)
            {
                return false;
            }
            else
            {
                word = "";
                ++j;
            }
        }
        else if (!mpe.count(word))
        {
            mp[pattern[i]] = word;
            mpe[word] = pattern[i];
            word = "";
            ++j;
        }
        else {
            return false;
        }

    }
    if (i < pattern.size() || j < s.length())
        return false;
    return true;
}

};



//https://leetcode.cn/problems/separate-black-and-white-balls/?envType=daily-question&envId=2024-06-06
//2938. 区分黑球与白球
long long minimumSteps(string s) {
    long long res = 0;
    int n = s.size();

    int left = 0, right = n - 1;

    while (left < right) {
        if (s[right] == '1')
            right--;
        else if (s[left] == '1' && s[right] == '0')
        {
            res += right - left;
            left++;
            right--;
        }
        else if (s[left] == '0' && s[right] == '0')
            left++;

    }

    return res;


}


//https://leetcode.cn/problems/maximum-number-of-operations-with-the-same-score-i/?envType=daily-question&envId=2024-06-07
//3038. 相同分数的最大操作数目 I
class Solution {
public:
    int maxOperations(vector<int>& nums)
    {
        int n = nums.size();
        int sum = nums[0] + nums[1];
        int cnt = 0;
        for (int i = 0; i < n; i += 2)
        {
            if (i + 1 < n && nums[i] + nums[i + 1] == sum)
                cnt++;
            else
                break;
        }
        return cnt;
    }
};



//https://leetcode.cn/problems/count-complete-tree-nodes/?envType=study-plan-v2&envId=top-interview-150
//222. 完全二叉树的节点个数
class Solution {
public:
    int dfs(TreeNode* root)
    {
        if (!root)
            return 0;
        return dfs(root->left) + dfs(root->right) + 1;
    }

    int countNodes(TreeNode* root) {
        return dfs(root);
    }
};


int countNodes(TreeNode* root)
{
    if (!root)
        return 0;
    return countNodes(root->left) + countNodes(root->right) + 1;;
}


//https://leetcode.cn/problems/balanced-binary-tree/
//110. 平衡二叉树
class Solution {
public:
    //求深度
    int height(TreeNode* root)
    {
        if (!root)
            return 0;
        return max(height(root->left), height(root->right)) + 1;
    }

    bool _isbalanced(TreeNode* root)
    {
        if (!root)
            return true;
        return abs(height(root->left) - height(root->right)) <= 1 && (_isbalanced(root->left) && _isbalanced(root->right));
    }
    bool isBalanced(TreeNode* root)
    {
        //平衡二叉树
        //AVL树， 左右子树差不超过1的树
        return _isbalanced(root);
    }
};


//55. 跳跃游戏
//https://leetcode.cn/problems/jump-game/
bool canJump(vector<int>& nums)
{
    //如果能到 2 ，说明 0 1 2 都能到
    int n = nums.size();
    int rightmax = 0;
    for (int i = 0; i < n; ++i)
    {
        if (i <= rightmax)
        {
            rightmax = max(rightmax, i + nums[i]);
            //cout <<rightmax<<endl; 
            if (rightmax >= n - 1)
                return true;
        }
    }
    return false;


}

//
//https://leetcode.cn/problems/boats-to-save-people/?envType=daily-question&envId=2024-06-10
//881. 救生艇
int numRescueBoats(vector<int>& people, int limit)
{
    sort(people.begin(), people.end());
    int left = 0, right = people.size() - 1;
    int cnt = 0;
    while (left <= right)
    {
        if (people[left] + people[right] > limit)
        {
            --right;
        }
        else
        {
            --right;
            ++left;
        }

        ++cnt;
    }
    return cnt;
}


//419. 甲板上的战舰 
//https://leetcode.cn/problems/battleships-in-a-board/description/?envType=daily-question&envId=2024-06-11
class Solution {
public:
    //只要判断 如果当前位置为X 只要判断右下角是不是X 就行
    int countBattleships(vector<vector<char>>& board)
    {
        //遍历矩阵
        int m = board.size();
        int n = board[0].size();
        int ret = 0;
        for (int i = 0; i < m; ++i)
        {
            for (int j = 0; j < n; ++j)
            {
                if (board[i][j] == 'X')
                {
                    //遍历整个表 把有X的改为.并且把这一行这一列遇到X前都改成.
                    board[i][j] = '.';
                    for (int k = j + 1; k < n && board[i][k] == 'X'; ++k)
                    {
                        board[i][k] = '.';
                    }
                    for (int k = i + 1; k < m && board[k][j] == 'X'; ++k)
                    {
                        board[k][j] = '.';
                    }
                    // Print(board);
                    // cout<<endl;
                    // cout<<endl;
                    ret++;
                }
            }
        }
        return ret;
    }
    void Print(vector<vector<char>>& board)
    {
        for (auto& arr : board)
        {
            for (auto& e : arr)
            {
                cout << e << " ";
            }
            cout << endl;
        }
    }
};

//https://leetcode.cn/problems/account-balance-after-rounded-purchase/?envType=daily-question&envId=2024-06-12
//2806. 取整购买后的账户余额
int accountBalanceAfterPurchase(int purchaseAmount)
{
    int temp = purchaseAmount / 10;
    if (purchaseAmount % 10 >= 5)
        temp += 1;
    return 100 - temp * 10;



}



//https://leetcode.cn/problems/insert-delete-getrandom-o1/?envType=study-plan-v2&envId=top-interview-150
//380. O(1) 时间插入、删除和获取随机元素
class RandomizedSet {
private:
    vector<int> nums_;
    unordered_map<int, int> hash_;
public:
    RandomizedSet() {
        //随机数种子
        srand(time(nullptr));
    }

    bool insert(int val) {
        cout << endl;
        if (hash_.count(val) == 0)
        {
            int pos = nums_.size();
            nums_.push_back(val);
            hash_[val] = pos;
            return true;
        }
        return false;
    }

    bool remove(int val) {
        if (hash_.find(val) == 0)
            return false;

        int pos = hash_[val];

        //这样也行
        int lastpos = nums_.size() - 1;
        hash_[nums_[lastpos]] = pos;
        swap(nums_[pos], nums_[lastpos]);

        //这样也行
        // int last = nums_.back();
        // nums_[pos] = last;
        // hash_[last] = pos;
        nums_.pop_back();
        hash_.erase(val);
        return true;
    }

    int getRandom() {
        // for(auto& e: nums_)
        //     cout << e <<" ";
        int pos = rand() % nums_.size();
        //cout<< nums_.size() <<endl;
        return nums_[pos];
    }
};


//https://leetcode.cn/problems/visit-array-positions-to-maximize-score/submissions/539517400/?envType=daily-question&envId=2024-06-14
//2786. 访问数组中的位置使分数最大
long long maxScore(vector<int>& nums, int x)
{
    int n = nums.size();
    vector<long long> dp(2, INT_MIN);
    long long  res = nums[0];
    dp[nums[0] % 2] = nums[0];
    //

    for (int i = 1; i < n; ++i)
    {
        int parity = nums[i] % 2;
        long long cur = max(dp[parity] + nums[i], dp[1 - parity] - x + nums[i]);
        res = max(res, cur);
        dp[parity] = max(dp[parity], cur);
    }

    return res;
}


//https://leetcode.cn/problems/maximum-beauty-of-an-array-after-applying-operation/?envType=daily-question&envId=2024-06-15
//2779. 数组的最大美丽值
int maximumBeauty(vector<int>& nums, int k)
{
    //排序  假设最大的美丽值是x 只要在 排序后的数组中找到 x -2 
    int ret = 0;
    int n = nums.size();
    sort(nums.begin(), nums.end());

    for (int left = 0, right = 0; right < n; ++right)
    {
        while (nums[right] - 2 * k > nums[left])
            left++;

        ret = max(ret, right - left + 1);
    }
    return ret;
}


//https://leetcode.cn/problems/longest-uncommon-subsequence-i/?envType=daily-question&envId=2024-06-16
//521. 最长特殊序列 Ⅰ
int findLUSlength(string a, string b)
{
    if (a == b)
        return -1;
    return max(a.size(), b.size());
}


//https://leetcode.cn/problems/longest-uncommon-subsequence-ii/?envType=daily-question&envId=2024-06-17
// 522. 最长特殊序列 II
//判断是否是子串
int pos1 = 0, pos2 = 0;
while (pos1 < str1.size() && pos2 < str2.size())
{
    if (str1[pos1] == str2[pos2])
    {
        pos1++;
    }
    pos2++;
}
return pos1 == str1.size();
    }

    int findLUSlength(vector<string>& strs)
    {
        int ret = -1;
        int n = strs.size();
        for (int i = 0; i < n; ++i)
        {
            bool check = true;

            for (int j = 0; j < n; ++j)
            {
                if (i != j && is_substr(strs[i], strs[j]))
                {
                    check = false;
                    break;
                }
            }
            if (check)
                ret = max(ret, (int)strs[i].size());
        }
        return ret;

    }

//https://leetcode.cn/problems/apply-discount-to-prices/submissions/540460591/?envType=daily-question&envId=2024-06-18
//2288. 价格减免
string discountPrices(string sentence, int discount)
{
    int n = sentence.size();
    sentence.push_back(' ');
    //通过空格分割每一个字串
    vector<string> words;
    int left = 0;
    int right = sentence.find(" ");
    while (right != std::string::npos)
    {
        string temp = sentence.substr(left, right - left);
        if (temp[0])

            words.push_back(temp);
        words.push_back(" ");
        left = right + 1;
        right = sentence.find(" ", right + 1);
    }

    for (auto& str : words)
    {

    }
    return "";

}


//https://leetcode.cn/submissions/detail/540668456/
//322. 零钱兑换
class Solution {
public:
    int coinChange(vector<int>& coins, int amount)
    {
        // vector<int> dp(amount+1, -1);
        // dp[0] = 0;
        // for(int i = 0; i < coins.size(); ++i)
        // {
        //     dp[coins[i]] = 1;
        // }

        // for(int i = 1; i < amount+1; ++i)
        // {
        //     for(int j = 0; j < coins.size(); ++j)
        //     {
        //         if(i - coins[j] >= 0)
        //             dp[i] = min(dp[i - coins[j]], dp[i]);

        //     }

        // }
        int Max = amount + 1;
        vector<int> dp(amount + 1, Max);
        dp[0] = 0;
        for (int i = 1; i <= amount; ++i) {
            for (int j = 0; j < (int)coins.size(); ++j)
            {
                if (coins[j] <= i)
                {
                    dp[i] = min(dp[i], dp[i - coins[j]] + 1);
                }
            }
        }
        return dp[amount] > amount ? -1 : dp[amount];

    }

};


//2748. 美丽下标对的数目
//https://leetcode.cn/problems/number-of-beautiful-pairs/description/?envType=daily-question&envId=2024-06-20
int countBeautifulPairs(vector<int>& nums) {
    int n = nums.size();
    int ret = 0;
    for (int i = 0; i < n; ++i)
    {
        while (nums[i] >= 10)
            nums[i] /= 10;

        for (int j = i + 1; j < n; ++j)
        {
            if (gcd(nums[i], nums[j] % 10) == 1)
                ret++;
        }
    }
    return ret;
}


class Solution {
public:
    // int get_trend(int x, int y)
    // {
    //     if(x == y)
    //         return 0;
    //     return x > y ? 1 : -1;
    // }
    // int temperatureTrend(vector<int>& temperatureA, vector<int>& temperatureB) 
    // {
    //     int n = temperatureA.size();
    //     int ret = 0; int cur = 0;
    //     for(int i = 1; i < n; ++i)
    //     {
    //         //可以写一个判断 趋势的函数
    //         int a = get_trend(temperatureA[i-1], temperatureA[i]);
    //         int b = get_trend(temperatureB[i-1], temperatureB[i]);
    //         if(a == b)
    //         {
    //             cur++;
    //             ret = max(ret, cur);
    //         }
    //         else
    //             cur = 0;
    //     }

    //     return ret;
    // }


    //LCP 61. 气温变化趋势
    //https://leetcode.cn/problems/6CE719/?envType=daily-question&envId=2024-06-21
    int temperatureTrend(vector<int>& temperatureA, vector<int>& temperatureB)
    {
        //使用 包装器
        function<int(int, int)> get_trend = [](int x, int y) -> int
            {
                if (x == y)
                    return 0;

                return x < y ? -1 : 1;
            };
        int n = temperatureA.size();
        int ret = 0; int cur = 0;
        for (int i = 1; i < n; ++i)
        {
            //可以写一个判断 趋势的函数
            int a = get_trend(temperatureA[i - 1], temperatureA[i]);
            int b = get_trend(temperatureB[i - 1], temperatureB[i]);
            if (a == b)
            {
                cur++;
                ret = max(ret, cur);
            }
            else
                cur = 0;
        }

        return ret;
    }


};


//LCR 126. 斐波那契数
//https://leetcode.cn/problems/fei-bo-na-qi-shu-lie-lcof/
int fib(int n)
{
    if (n < 2)
        return n;
    vector<int> dp(n + 1);
    dp[0] = 0;
    dp[1] = 1;
    for (int i = 2; i <= n; ++i)
    {
        dp[i] = dp[i - 1] + dp[i - 2];
        dp[i] %= 1000000007;
    }
    return dp[n];

}



//https://leetcode.cn/problems/detect-capital/solutions/1097378/jian-ce-da-xie-zi-mu-by-leetcode-solutio-449z/?envType=daily-question&envId=2024-06-23
//520. 检测大写字母

class Solution {
public:
    bool detectCapitalUse(string word)
    {
        //判断第一个字母是否是小写
        if (word.size() >= 2 && word[0] >= 'a' && word[1] <= 'Z')
            return false;

        //从下表2 开始 后面都必须要是一样的才行
        for (int i = 2; i < word.size(); ++i)
        {
            if (islower(word[i]) && islower(word[i - 1]) || isupper(word[i]) && isupper(word[i - 1]))
                continue;
            else
                return false;
        }
        return true;
    }

};


//503. 下一个更大元素 II
//https://leetcode.cn/problems/next-greater-element-ii/submissions/541736032/?envType=daily-question&envId=2024-06-24
class Solution {
public:
    vector<int> nextGreaterElements(vector<int>& nums)
    {
        stack<int> st;
        int n = nums.size();
        vector<int> ret(nums.size(), -1);
        for (int i = 0; i < n * 2 - 1; ++i)
        {
            while (!st.empty() && nums[st.top()] < nums[i % n])
            {
                ret[st.top()] = nums[i % n];
                st.pop();
            }
            st.push(i % n);
        }
        return ret;
    }


};


//https://leetcode.cn/problems/zigzag-conversion/
//6. Z 字形变换
class Solution {
public:
    string convert(string s, int numRows)
    {
        if (numRows < 2)
            return s;
        //模拟这个行索引的变化，在遍历 s 中把每个字符填到正确的行 res[i] 
        int flag = -1;
        vector<string> rows(numRows);
        int i = 0;
        for (auto& c : s)
        {
            rows[i].push_back(c);
            if (i == 0)
            {
                flag = -flag;
            }
            if (i == numRows - 1)
            {
                flag = -flag;
            }
            i += flag;
        }

        string ret;
        for (auto& str : rows)
        {
            ret += str;
        }
        return ret;
    }

    //有点意思 我的想法是 先找出列数 在
    // int n = s.size();
    // //确定列数
    // int col = 0;
    // while(n)
    // {
    //     if(n - numRows >= 0)
    //     {
    //         col++;
    //         n -= numRows;
    //         if(n == 0)
    //             break;
    //     }
    //     else
    //     {
    //         col++;
    //         break;
    //     }

    //     if(n - (numRows-2) >= 0)
    //     {
    //         col += numRows -2;
    //         n -= (numRows-2);
    //         //
    //     }
    //     else
    //     {
    //         col += n;
    //         break;
    //     }
    // }

    // cout << col ;

    // return "";
//}

};


//https://leetcode.cn/problems/contiguous-sequence-lcci/
//面试题 16.17. 连续数列
int maxSubArray(vector<int>& nums)
{
    //动态规划
    int n = nums.size();
    if (n == 1)
        return nums[0];
    vector<int> dp(n, 0);
    dp[0] = nums[0];
    int ret = nums[0];
    for (int i = 1; i < n; ++i)
    {
        dp[i] = max(dp[i - 1] + nums[i], nums[i]);
        //cout << dp[i] <<endl;
        ret = max(ret, dp[i]);
    }

    return ret;
}


//https://leetcode.cn/problems/remove-trailing-zeros-from-a-string/?envType=daily-question&envId=2024-06-29
//2710. 移除字符串中的尾随零
string removeTrailingZeros(string num)
{
    int i = num.size() - 1;
    while (num[i] == '0')
        i--;
    return num.substr(0, i + 1);
}


//https://leetcode.cn/problems/target-sum/?envType=daily-question&envId=2024-06-30
//494. 目标和
class Solution {
public:
    int count = 0;

    void backtrack(vector<int>& nums, int target, int index, int sum)
    {
        //如果走到最后了  看一下是否是target
        if (index == nums.size())
        {
            if (sum == target)
                count++;
        }
        else  //需要+else 不然会overflow 
        {
            backtrack(nums, target, index + 1, sum + nums[index]);
            backtrack(nums, target, index + 1, sum - nums[index]);
        }
    }

    int findTargetSumWays(vector<int>& nums, int target)
    {
        //回溯 过程中维护 count
        backtrack(nums, target, 0, 0);
        return count;
    }
};


//https://leetcode.cn/problems/t9-lcci/
//面试题 16.20. T9键盘
vector<string> getValidT9Words(string num, vector<string>& words)
{
    vector<string> hash = { "", "", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz" };
    vector<string> ret;
    vector<int> nums;

    //转换成数字数组
    for (int i = 0; i < num.size(); ++i)
        nums.push_back(num[i] - '0');


    int n = words.size();
    for (int i = 0; i < n; ++i)
    {
        int flag = true;
        for (int j = 0; j < words[i].size(); ++j)
        {
            if (hash[nums[j]].find(words[i][j]) == std::string::npos)
            {
                flag = false;
                break;
            }
        }

        if (flag)
            ret.push_back(words[i]);
    }
    return ret;
}


//https://leetcode.cn/problems/maximum-prime-difference/?envType=daily-question&envId=2024-07-02
//3115. 质数的最大距离
class Solution {
public:
    bool isPrime(int x)
    {
        if (x <= 1)
            return false;
        for (int i = 2; i <= sqrt(x); ++i)
        {
            if (x % i == 0)
                return false;
        }
        return true;
    }

    int maximumPrimeDifference(vector<int>& nums)
    {
        int n = nums.size();
        int left = n - 1;
        int right = 0;
        for (int i = 0; i < n; ++i)
        {
            if (isPrime(nums[i]))
            {
                left = min(left, i);
                right = max(right, i);
            }
        }
        return right - left;
    }

};



//https://leetcode.cn/problems/minimum-absolute-difference-in-bst/
//530. 二叉搜索树的最小绝对差
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    // void dfs(TreeNode* root, int& sum)
    // {
    //     if(root == nullptr)
    //         return;

    //     if(root->left != nullptr)
    //         sum = min(sum, abs(root->val - root->left->val));
    //     if(root->right != nullptr)
    //         sum = min(sum, abs(root->val - root->right->val));

    //     dfs(root->left, sum);
    //     dfs(root->right, sum);           
    // }

    void dfs(TreeNode* root, int& pre, int& ret)
    {
        if (root == nullptr)
            return;

        dfs(root->left, pre, ret);
        if (pre == -1)
            pre = root->val;
        else
        {
            ret = min(ret, root->val - pre);
            pre = root->val;
        }
        dfs(root->right, pre, ret);

    }
    int getMinimumDifference(TreeNode* root)
    {
        //中序遍历 二叉搜索树 是规律递增的
        int ret = INT_MAX;
        int pre = -1;   //使用pre来保存前面一个的值
        dfs(root, pre, ret);
        return ret;
    }


};


//https://leetcode.cn/problems/harshad-number/description/?envType=daily-question&envId=2024-07-03
//3099. 哈沙德数
int sumOfTheDigitsOfHarshadNumber(int x)
{
    int n = x;
    int sum = 0;
    while (n)
    {
        sum += (n % 10);
        n /= 10;
    }
    return x % sum == 0 ? sum : -1;


}


//https://leetcode.cn/problems/find-closest-lcci/
//面试题 17.11. 单词距离
int findClosest(vector<string>& words, string word1, string word2)
{
    int n = words.size();
    int min_length = INT_MAX;
    int pos1 = -1, pos2 = -1;
    for (int i = 0; i < n; ++i)
    {
        if (words[i] == word1)
            pos1 = i;
        if (words[i] == word2)
            pos2 = i;

        if (pos1 > 0 && pos2 > 0)
            min_length = min(min_length, abs(pos1 - pos2));
    }
    return min_length;

}


//https://leetcode.cn/problems/missing-two-lcci/submissions/544106862/
//面试题 17.19. 消失的两个数字
vector<int> missingTwo(vector<int>& nums)
{
    //参考 260. 只出现一次的数字 III   面试题 17.04. 消失的数字
    // 把所有的数异或在一起 1-->n  以及 1-->n 少两个数 a b 
    //最后就能得到 a^b 
    int n = nums.size() + 2;
    int temp = 0;
    for (int i = 1; i <= n; ++i)
        temp ^= i;
    for (int i = 0; i < nums.size(); ++i)
        temp ^= nums[i];

    cout << temp << endl;
    //得到了 a^b 的值
    //需要对 a 和 b 分组
    // 找出 从右往左 第一位 a b 为1 bit 位
    // 3 ^ 5  011 ^ 101 = 110
    int pos = 0;
    for (int i = 0; i < 32; ++i)
    {
        if (((temp >> i) & 1) == 1)
        {
            pos = i;
            break;
        }
    }
    cout << pos;

    //进行分组
    vector<int> disappear(2);
    for (auto& e : nums)
    {
        if (((e >> pos) & 1) == 1)
            disappear[0] ^= e;
        else
            disappear[1] ^= e;
    }
    for (int i = 1; i <= n; ++i)
    {
        if (((i >> pos) & 1) == 1)
            disappear[0] ^= i;
        else
            disappear[1] ^= i;
    }

    return disappear;

}


//https://leetcode.cn/problems/modify-the-matrix/?envType=daily-question&envId=2024-07-05
//3033. 修改矩阵
vector<vector<int>> modifiedMatrix(vector<vector<int>>& matrix)
{
    // auto ret = matrix;
    int col = matrix[0].size();
    int row = matrix.size();

    for (int i = 0; i < col; ++i)
    {
        int max_col = -2;
        for (int j = 0; j < row; ++j)
            max_col = max(max_col, matrix[j][i]);

        for (int j = 0; j < row; ++j)
        {
            if (matrix[j][i] == -1)
                matrix[j][i] = max_col;
        }
    }
    return matrix;

}


//https://leetcode.cn/problems/count-alternating-subarrays/?envType=daily-question&envId=2024-07-06
//3101. 交替子数组计数
long long countAlternatingSubarrays(vector<int>& nums)
{
    //或者用遍历
    // 记录上一个数的数值和当前最长交替子数组的长度。如果当前数和之前的数不一样，则交替子数组的长度加一，否则交替子数组长度为一
    long long ret = 0, dp = 1;
    //dp是第一个元素
    for (int i = 1; i < nums.size(); ++i)
    {
        if (nums[i] == nums[i - 1])
            dp = 1;
        else
            dp = dp + 1;

        ret += dp;
    }
    return ret + 1;
}
// long long countAlternatingSubarrays(vector<int>& nums) 
// {
//     int n = nums.size();
//     vector<long long> dp(n+1, 0);

//     dp[0] = 1;
//     for(long long i = 1; i < n; ++i)
//     {
//         if(nums[i] == nums[i-1])
//         {
//             dp[i] = dp[i-1] + 1;
//         }
//         else
//         {
//             if(i-2 >= 0)
//                 dp[i] = dp[i-1] + dp[i-1] - dp[i-2] + 1;
//             else
//                 dp[i] = dp[i-1] + dp[i-1] + 1;
//         }
//     }
//     return dp[n-1];
// }



//https://leetcode.cn/problems/check-if-move-is-legal
//1958. 检查操作是否合法
bool checkMove(vector<vector<char>>& board, int rMove, int cMove, char color)
{
    //端点
    //8个方向去验证
    int m = board.size();
    int n = board[0].size();
    board[rMove][cMove] = color;

    //横
    for (int j = cMove - 1; j >= 0; --j)
    {
        if (board[rMove][j] == '.')
            break;
        if (board[rMove][j] == color)
        {
            if (cMove - j >= 2)
            {
                cout << 1 << endl;
                return true;
            }
            else
                break; //如果开头两个连续一样 说明不是
        }
    }

    for (int j = cMove + 1; j < m; ++j)
    {
        if (board[rMove][j] == '.')
            break;
        if (board[rMove][j] == color)
        {
            if (j - cMove >= 2)
            {
                cout << 2 << endl;
                return true;
            }
            else
                break; //如果开头两个连续一样 说明不是
        }
    }

    //竖
    for (int i = rMove - 1; i >= 0; --i)
    {
        if (board[i][cMove] == '.')
            break;
        if (board[i][cMove] == color)
        {
            if (abs(rMove - i) >= 2)
            {
                cout << 3 << endl;
                return true;
            }
            else
                break; //如果开头两个连续一样 说明不是
        }
    }

    for (int i = rMove + 1; i < n; ++i)
    {
        if (board[i][cMove] == '.')
            break;
        if (board[i][cMove] == color)
        {
            if (abs(rMove - i) >= 2)
            {
                cout << 4 << endl;
                return true;
            }
            else
                break; //如果开头两个连续一样 说明不是
        }
    }

    //正对角
    for (int i = rMove - 1, j = cMove - 1; i >= 0 && j >= 0; i--, j--)
    {
        if (board[i][j] == '.')
            break;
        if (board[i][j] == color)
        {
            if (rMove - i >= 2)
            {
                cout << 5 << endl;
                return true;
            }
            else
                break;
        }
    }

    for (int i = rMove + 1, j = cMove + 1; i < m && j < n; i++, j++)
    {
        if (board[i][j] == '.')
            break;
        if (board[i][j] == color)
        {
            if (i - rMove >= 2)
            {
                cout << 6 << endl;
                return true;
            }
            else
                break;
        }
    }

    //反对角
    for (int i = rMove - 1, j = cMove + 1; i >= 0 && j < n; i--, j++)
    {
        if (board[i][j] == '.')
            break;
        if (board[i][j] == color)
        {
            if (rMove - i >= 2)
            {
                cout << 7 << endl;
                return true;
            }
            else
                break;
        }
    }

    for (int i = rMove + 1, j = cMove - 1; i < m && j >= 0; i++, j--)
    {
        if (board[i][j] == '.')
            break;
        if (board[i][j] == color)
        {
            if (i - rMove >= 2)
            {
                cout << 8 << endl;
                return true;
            }
            else
                break;
        }
    }
    return false;

}



//724. 寻找数组的中心下标
//https://leetcode.cn/problems/find-pivot-index/?envType=daily-question&envId=2024-07-08
int pivotIndex(vector<int>& nums)
{
    int sum = 0;
    for (auto e : nums)
        sum += e;

    int piv = 0;
    for (int i = 0; i < nums.size(); ++i)
    {
        if (piv == sum - piv - nums[i])
        {
            return i;
        }
        piv += nums[i];
    }
    return -1;


}

//https://leetcode.cn/problems/replace-all-s-to-avoid-consecutive-repeating-characters/
//1576. 替换所有的问号

string modifyString(string s)
{
    int n = s.size();
    for (int i = 0; i < n; ++i)
    {
        //从前向后遍历 遇到 ? 判断 
        if (s[i] == '?')
        {
            for (char ch = 'a'; ch <= 'z'; ++ch)
            {
                if ((i == 0 || ch != s[i - 1]) && (i == n - 1 || ch != s[i + 1]))
                {
                    s[i] = ch;
                    break;
                }
            }
        }
    }
    return s;

}

//https://leetcode.cn/problems/teemo-attacking/
//495. 提莫攻击
int findPoisonedDuration(vector<int>& timeSeries, int duration)
{
    int n = timeSeries.size();
    int ret = 0;
    //来一个值记录 中毒的持续的时间
    int expired = 0;
    for (int i = 0; i < n; ++i)
    {
        if (timeSeries[i] >= expired)
        {
            ret += duration;
        }
        else
        {
            ret += timeSeries[i] + duration - expired;
        }

        expired = timeSeries[i] + duration;
    }
    return ret;
}


//https://leetcode.cn/problems/spiral-matrix/
//54. 螺旋矩阵
vector<int> spiralOrder(vector<vector<int>>& matrix)
{
    //用四条边线代表范围进行搜索
    int left = 0, right = matrix[0].size() - 1;
    int top = 0, bottom = matrix.size() - 1;

    vector<int> ret;

    while (true)
    {
        //从左向右打印
        for (int i = left; i <= right; ++i)
            ret.push_back(matrix[top][i]);
        if (++top > bottom)    // ++ 判断先加在判断 可以合在一起 判断是否越界 上边界是否超过了下边界
            break;

        //从上往下打印
        for (int i = top; i <= bottom; ++i)
            ret.push_back(matrix[i][right]);
        if (--right < left) //判断是否越界 右边界是否超过了左边界
            break;

        //从右往左打印
        for (int i = right; i >= left; --i)
            ret.push_back(matrix[bottom][i]);
        if (--bottom < top)//判断是否越界 下边界是否超过了上边界
            break;

        //从下往上打印
        for (int i = bottom; i >= top; --i)
            ret.push_back(matrix[i][left]);
        if (++left > right) //判断是否越界 左边界是否超过了右边界
            break;
    }

    return ret;


}


//https://leetcode.cn/problems/count-the-number-of-incremovable-subarrays-i/solutions/2834778/tong-ji-yi-chu-di-zeng-zi-shu-zu-de-shu-0ujed/?envType=daily-question&envId=2024-07-10
//2970. 统计移除递增子数组的数目 I
int incremovableSubarrayCount(vector<int>& nums)
{
    int n = nums.size();
    int ret = 0;
    int left = 1;
    while (left < n && nums[left - 1] < nums[left])
    {
        left++;
    }
    // 如果开始是降序的 4 2 3 5.. left 是 1
    ret += left;
    //并且还要判断 如果 left 是小于 n 的
    // 如果全是升序 1 2 3 5 6  left   +5
    // 如果是 5 6 7 4 8  left 是 3 + 1
    ret += (left < n);


    //判断right  并且保持左半边数组递增， 右边数组也递增，并且保证 左边的最大数要小于右边的最小数
    for (int right = n - 2; right >= 0; --right)
    {
        while (left > 0 && nums[left - 1] >= nums[right + 1])
        {
            left--;
        }
        ret += left + (left <= right);
        if (nums[right] >= nums[right + 1])
            break;
    }
    return ret;


}


//https://leetcode.cn/problems/count-the-number-of-incremovable-subarrays-ii/description/?envType=daily-question&envId=2024-07-11
//2972. 统计移除递增子数组的数目 II
long long incremovableSubarrayCount(vector<int>& nums)
{
    long long ret = 0;
    int len = nums.size();
    int left = 0;
    while (left < len - 1)
    {
        if (nums[left] >= nums[left + 1])
            break;
        left++;
    }

    if (left == len - 1)
        return (long long)(len * (len + 1) / 2);

    //如果left不是最后一个下表
    ret += left + 2;
    for (int right = len - 1; right > 0; --right)
    {
        if (right < len - 1 && nums[right] >= nums[right + 1]) {
            break;
        }

        while (left >= 0 && nums[left] >= nums[right]) {
            left--;
        }
        ret += left + 2;
    }
    return ret;
}
// long long incremovableSubarrayCount(vector<int>& nums) 
// {
//     int n = nums.size();
//     long long ret = 0;
//     int left = 1;
//     while(left < n && nums[left - 1] < nums[left])
//     {
//         left++;
//     }
//     // 如果开始是降序的 4 2 3 5.. left 是 1
//     ret += left;
//     //并且还要判断 如果 left 是小于 n 的
//     // 如果全是升序 1 2 3 5 6  left   +5
//     // 如果是 5 6 7 4 8  left 是 3 + 1
//     ret += (left < n);


//     //判断right  并且保持左半边数组递增， 右边数组也递增，并且保证 左边的最大数要小于右边的最小数
//     for(int right = n - 2; right >= 0; --right)
//     {
//         while(left > 0 && nums[left-1] >= nums[right+1])
//         {
//             left--;
//         }
//         ret += left + (left <= right);
//         if(nums[right] >= nums[right+1])
//             break;
//     }
//     return ret;

// }


//https://leetcode.cn/problems/minimum-number-game/?envType=daily-question&envId=2024-07-12
//2974. 最小数字游戏
vector<int> numberGame(vector<int>& nums)
{
    vector<int> ret;
    sort(nums.begin(), nums.end());
    for (int i = 1; i < nums.size(); i += 2)
    {
        ret.push_back(nums[i]);
        ret.push_back(nums[i - 1]);
    }
    return ret;
}


//https://leetcode.cn/problems/find-if-array-can-be-sorted/?envType=daily-question&envId=2024-07-13
//3011. 判断一个数组是否可以变为有序
class Solution {
public:
    //判断二进制中 1 的个数
    int binarycount(int num)
    {
        int count = 0;
        while (num)
        {
            num &= num - 1;
            count++;
        }
        return count;
    }

    bool canSortArray(vector<int>& nums)
    {
        int n = nums.size();
        for (int i = 0; i < n; )
        {
            //因为是临近的两个数才能排序 判断临近的两个数是不是有相同的 1 的个数
            int start = i;
            int cnt = __builtin_popcount(nums[i++]);
            while (i < n && __builtin_popcount(nums[i]) == cnt)
            {
                i++;
            }
            //
            sort(nums.begin() + start, nums.begin() + i);
        }

        //判断最后是数组是否 是有序的
        // for(int i = 1; i < n; ++i)
        // {
        //     if(nums[i] < nums[i-1])
        //         return false;
        // }
        return is_sorted(nums.begin(), nums.end());
    }
};


//https://leetcode.cn/problems/max-increase-to-keep-city-skyline/?envType=daily-question&envId=2024-07-14
//807. 保持城市天际线
int maxIncreaseKeepingSkyline(vector<vector<int>>& grid)
{
    int m = grid.size();
    int n = grid[0].size();
    //需要找出每一行每一列的最大值
    vector<int> row_max(m, 0);
    vector<int> col_max(m, 0);

    for (int i = 0; i < m; ++i)
    {
        for (int j = 0; j < n; ++j)
        {
            row_max[i] = max(row_max[i], grid[i][j]);
            col_max[j] = max(col_max[j], grid[i][j]);
        }
    }

    // for(auto e : row_max)
    // {
    //     cout<<e<<" ";
    // }
    // cout<<endl;
    // for(auto e : col_max)
    // {
    //     cout<<e<<" ";
    // }
    int sum = 0;
    for (int i = 0; i < m; ++i)
    {
        for (int j = 0; j < n; ++j)
        {
            sum += min(row_max[i], col_max[j]) - grid[i][j];
        }
    }
    return sum;


}


//https://leetcode.cn/problems/count-and-say/submissions/546520631/
//38. 外观数列
string countAndSay(int n)
{
    string ret = "1";
    for (int i = 0; i < n - 1; ++i) //对 i n-1次解释
    {
        string tmp;
        int len = ret.size();
        for (int left = 0, right = 0; right < len; )
        {
            while (right < len && ret[left] == ret[right])
                right++;

            tmp += to_string(right - left) + ret[left];
            //tmp += ret[left];
            left = right;
        }
        ret = tmp;
    }
    return ret;

}



//https://leetcode.cn/problems/accounts-merge/?envType=daily-question&envId=2024-07-15
//721. 账户合并
class UnionFind
{
public:
    UnionFind(int n)
    {
        p = vector<int>(n);
        size = vector<int>(n, 0);
        //将位置下标初始化好 p 中从 0 到 n-1
        //C++ 函数 itoa 从 0 开始递增
        iota(p.begin(), p.end(), 0);
    }

    bool unite(int a, int b)
    {
        int pa = find(a), pb = find(b);
        if (pa == pb)
            return false;

        if (size[pa] > size[pb])
        {
            p[pb] = pa;
            size[pa] += size[pb];
        }
        else
        {
            p[pa] = pb;
            size[pb] += size[pa];
        }
        return true;
    }

    int find(int x)
    {
        if (p[x] != x)
        {
            p[x] = find(p[x]);
        }
        return p[x];
    }

private:
    vector<int> p; //下标
    vector<int> size;
};

class Solution {
public:
    // ["John", "johnsmith@mail.com", "john00@mail.com"], 
    // ["John", "johnnybravo@mail.com"], 
    // ["John", "johnsmith@mail.com", "john_newyork@mail.com"], 
    // ["Mary", "mary@mail.com"]

    // ["John", 'john00@mail.com', 'john_newyork@mail.com', 'johnsmith@mail.com'],  
    // ["John", "johnnybravo@mail.com"], 
    // ["Mary", "mary@mail.com"]]
    vector<vector<string>> accountsMerge(vector<vector<string>>& accounts)
    {
        int n = accounts.size();
        UnionFind uf(n);
        unordered_map<string, int> dict;
        //首先遍历所有的账户 对于第 i 个账户， 遍历所有的邮箱地址
        for (int i = 0; i < n; ++i)
        {
            //遍历所有的邮箱地址
            for (int j = 1; j < accounts[i].size(); ++j)
            {
                const string& email = accounts[i][j];
                if (dict.find(email) != dict.end())
                {
                    //如果出现过  将该账户的编号 i 与之前出现过的邮箱地址所属的账户编号进行合并
                    //进行映射
                    uf.unite(i, dict[email]);
                }
                else
                {
                    dict[email] = i;
                }
            }
        }

        unordered_map<int, set<string>> g;
        for (int i = 0; i < n; ++i)
        {
            int root = uf.find(i);
            g[root].insert(accounts[i].begin() + 1, accounts[i].end());

        }

        vector<vector<string>> ans;
        for (auto& [root, s] : g)
        {
            vector<string> emails(s.begin(), s.end());
            emails.insert(emails.begin(), accounts[root][0]);
            ans.push_back(emails
            );
        }
        return ans;
    }

};


//https://leetcode.cn/problems/find-common-elements-between-two-arrays/?envType=daily-question&envId=2024-07-16
//2956. 找到两个数组中的公共元素
vector<int> findIntersectionValues(vector<int>& nums1, vector<int>& nums2)
{
    unordered_map<int, int> hash1;
    unordered_map<int, int> hash2;
    for (auto& e : nums1)
        hash1[e]++;
    for (auto& e : nums2)
        hash2[e]++;

    vector<int> ret(2, 0);
    for (auto e : nums1)
        if (hash2.find(e) != hash2.end())
            ret[0]++;

    for (auto e : nums2)
        if (hash1.find(e) != hash1.end())
            ret[1]++;

    return ret;
}


//https://leetcode.cn/problems/minimum-number-of-frogs-croaking/
//1419. 数青蛙
int minNumberOfFrogs(string croakOfFrogs)
{
    //更通用
    string t = "croak";
    int n = t.size();

    vector<int> hash(n); //用数组来模拟哈希表

    unordered_map<char, int> index; // 字符以及字符对应的下标
    for (int i = 0; i < n; ++i)
    {
        index[t[i]] = i;
    }

    for (auto ch : croakOfFrogs)
    {
        if (ch == 'c')
        {
            if (hash[n - 1] > 0)
                hash[n - 1]--;
            hash[0]++;
        }
        else
        {
            int i = index[ch];
            if (hash[i - 1] == 0)
                return -1;
            hash[i - 1]--;
            hash[i]++;
        }
    }

    for (int i = 0; i < n - 1; ++i)
    {
        if (hash[i] != 0)
            return -1;
    }
    return hash[n - 1];
}


int minNumberOfFrogs(string croakOfFrogs)
{
    unordered_map<char, int> hash = { {'c', 0}, {'r', 0}, {'o', 0}, {'a', 0}, {'k', 0} };
    int n = croakOfFrogs.size();

    for (int i = 0; i < n; ++i)
    {
        char tmp = croakOfFrogs[i];
        if (tmp == 'c')
        {
            if (hash['k'] > 0)
                hash['k']--;
            hash[tmp]++;
        }
        else if (tmp == 'r')
        {
            //找一下前面的c在不在
            if (hash['c'] > 0)
            {
                hash['c']--;
                hash[tmp]++;
            }
            else
                return -1;
        }
        else if (tmp == 'o')
        {
            if (hash['r'] > 0)
            {
                hash['r']--;
                hash[tmp]++;
            }
            else
                return -1;
        }
        else if (tmp == 'a')
        {
            if (hash['o'] > 0)
            {
                hash['o']--;
                hash[tmp]++;
            }
            else
                return -1;
        }
        else if (tmp == 'k')
        {
            if (hash['a'] > 0)
            {
                hash['a']--;
                hash[tmp]++;
            }
            else
                return -1;
        }
    }

    //在遍历一下 应该最后只有 'k'有值
    if (hash['c'] != 0 || hash['r'] != 0 || hash['o'] != 0 || hash['a'] != 0)
        return -1;
    return hash['k'];
}


//https://leetcode.cn/problems/valid-sudoku/
//36. 有效的数独
bool isValidSudoku(vector<vector<char>>& board)
{
    vector<vector<int>> rows(9, vector<int>(9));
    vector<vector<int>> cols(9, vector<int>(9));
    vector<vector<vector<int>>> subboxes(3, vector<vector<int>>(3, vector<int>(9)));
    //或者用 int row[9][9] 也可以
    for (int i = 0; i < 9; ++i)
    {
        for (int j = 0; j < 9; ++j)
        {
            char ch = board[i][j];
            if (ch != '.')
            {
                //hash映射 0-9映射0-9下标
                int index = ch - '0' - 1;
                rows[i][index]++;
                cols[j][index]++;
                subboxes[i / 3][j / 3][index]++;
                if (rows[i][index] > 1 || cols[j][index] > 1 || subboxes[i / 3][j / 3][index] > 1)
                    return false;
            }
        }
    }
    return true;
}


//https://leetcode.cn/problems/minimum-levels-to-gain-more-points/submissions/548103944/?envType=daily-question&envId=2024-07-19
//3096. 得到更多分数的最少关卡数目
int minimumLevels(vector<int>& possible)
{
    int n = possible.size();
    vector<int> pre(n);
    vector<int> end(n);

    pre[0] = possible[0] == 1 ? 1 : -1;
    end[n - 1] = possible[n - 1] == 1 ? 1 : -1;

    for (int i = 1; i < n; ++i)
        pre[i] += pre[i - 1] + (possible[i] == 1 ? 1 : -1);

    for (int i = n - 2; i >= 0; --i)
        end[i] += end[i + 1] + (possible[i] == 1 ? 1 : -1);

    for (int i = 0; i < n; ++i)
    {
        if (i + 1 < n && pre[i] > end[i + 1])
            return i + 1;
    }
    return -1;
}


//https://leetcode.cn/problems/minimum-moves-to-spread-stones-over-grid/?envType=daily-question&envId=2024-07-20
//2850. 将石头分散到网格图的最少移动次数
int minimumMoves(vector<vector<int>>& grid)
{
    vector<pair<int, int>> more, less;
    for (int i = 0; i < 3; ++i)
    {
        for (int j = 0; j < 3; ++j)
        {
            if (grid[i][j] > 1)
            {
                for (int k = 2; k <= grid[i][j]; ++k)
                {
                    more.push_back({ i, j });
                }
            }
            else if (grid[i][j] == 0)
            {
                less.push_back({ i, j });
            }
        }
    }

    //统计完了大于 1 和为空的格子的位置 每种情况都遍历一次
    int ret = INT_MAX;
    int n = 550;
    // while(n--)
    // {
    //     int step = 0;
    //     for(int i = 0; i < more.size(); ++i)
    //     {
    //         step += abs(more[i].first - less[i].first) + abs(more[i].second - less[i].second);
    //     }
    //     ret = min(ret, step); 
    // }
    int cnt = 0;
    do {
        int step = 0;
        for (int i = 0; i < more.size(); ++i)
        {
            // cout<<"more[i].first:"<<more[i].first<<" more[i].second:"<<more[i].second<<endl;
            // cout<<"less[i].first:"<<less[i].first<<" less[i].second:"<<less[i].second<<endl;
            step += abs(more[i].first - less[i].first) + abs(more[i].second - less[i].second);
        }
        ret = min(ret, step);
        //cnt++;

    } while (next_permutation(more.begin(), more.end()));

    //cout<<cnt;
    return ret;
}


//https://leetcode.cn/problems/permutations/
//46. 全排列
vector<vector<int>> permute(vector<int>& nums)
{
    //使用库函数试一下
    sort(nums.begin(), nums.end());
    vector<vector<int>> ret;
    do
    {
        ret.push_back(nums);
    } while (next_permutation(nums.begin(), nums.end()));

    return ret;
}


//https://leetcode.cn/problems/longest-increasing-subsequence/
//300. 最长递增子序列s
int lengthOfLIS(vector<int>& nums)
{
    int n = nums.size();
    int ret = 0;
    vector<int> dp(n);
    for (int i = 0; i < n; ++i)
    {
        dp[i] = 1;
        for (int j = 0; j < i; ++j)
        {
            if (nums[j] < nums[i])
            {
                dp[i] = max(dp[i], dp[j] + 1);
            }
            //cout<< dp[i] << endl;
        }
        ret = max(ret, dp[i]);
    }
    return ret;

}


//https://leetcode.cn/problems/3u1WK4/
//LCR 023. 相交链表

ListNode* getIntersectionNode(ListNode* headA, ListNode* headB)
{
    ListNode* pA = headA; ListNode* pB = headB;

    if (headA == nullptr || headB == nullptr)
        return nullptr;

    while (pA != pB)
    {
        pA = pA == nullptr ? headB : pA->next;
        pB = pB == nullptr ? headA : pB->next;
    }
    return pA;


}
ListNode* getIntersectionNode(ListNode* headA, ListNode* headB)
{
    ListNode* fast = headA;
    ListNode* slow = headB;
    int fast_count = 0;
    int slow_count = 0;

    while (headA)
    {
        headA = headA->next;
        fast_count++;
    }

    while (headB)
    {
        headB = headB->next;
        slow_count++;
    }

    if (fast_count > slow_count)
    {
        int gap = fast_count - slow_count;
        while (gap--)
        {
            fast = fast->next;
        }
    }
    if (fast_count < slow_count)
    {
        int gap = slow_count - fast_count;
        while (gap--)
        {
            slow = slow->next;
        }
    }

    while (fast && slow)
    {
        if (fast == slow)
            return fast;
        fast = fast->next;
        slow = slow->next;
    }
    return nullptr;
}


//https://leetcode.cn/problems/relocate-marbles/?envType=daily-question&envId=2024-07-24
//2766. 重新放置石块
vector<int> relocateMarbles(vector<int>& nums, vector<int>& moveFrom, vector<int>& moveTo)
{
    map<int, int> hash;
    for (auto& e : nums)
        hash[e]++;

    for (int i = 0; i < moveFrom.size(); ++i)
    {
        if (hash.count(moveFrom[i]))
        {
            hash.erase(moveFrom[i]);
            hash[moveTo[i]]++;
        }
    }

    vector<int> res;
    for (map<int, int>::iterator it = hash.begin(); it != hash.end(); ++it)
        res.push_back((*it).first);

    return res;
}


//https://leetcode.cn/problems/convert-binary-number-in-a-linked-list-to-integer/
//1290. 二进制链表转整数
int getDecimalValue(ListNode* head)
{
    int res = 0;
    ListNode* cur = head;
    while (cur)
    {
        res = res * 2 + cur->val;
        cur = cur->next;
    }

    return res;
}


//https://leetcode.cn/problems/find-the-value-of-the-partition/?envType=daily-question&envId=2024-07-26
//2740. 找出分区值
int findValueOfPartition(vector<int>& nums)
{
    sort(nums.begin(), nums.end());
    int res = INT_MAX;
    for (int i = 1; i < nums.size(); ++i)
    {
        res = min(nums[i] - nums[i - 1], res);
    }
    return res;
}


//https://leetcode.cn/problems/lexicographically-smallest-string-after-operations-with-constraint/?envType=daily-question&envId=2024-07-27
//3106. 满足距离约束且字典序最小的字符串
string getSmallestString(string s, int k)
{
    //字典序最小 前面的字母越小越好
    int n = s.size();
    for (int i = 0; i < n; ++i)
    {
        // int to_end = 'z' - s[i] + 1;
        // int to_head = s[i] - 'a';
        // int min_dis = min(to_end, to_head);
        int min_dis = min('z' - s[i] + 1, s[i] - 'a');
        if (min_dis <= k)
        {
            s[i] = 'a';
            k -= min_dis;
        }
        else
        {
            s[i] -= k;
            break;
        }
    }
    return s;
}


//https://leetcode.cn/problems/cong-wei-dao-tou-da-yin-lian-biao-lcof/
//LCR 123. 图书整理 I
vector<int> reverseBookList(ListNode* head) {
    vector<int> res;
    while (head)
    {
        res.push_back(head->val);
        head = head->next;
    }
    reverse(res.begin(), res.end());
    return res;
}


//https://leetcode.cn/problems/baseball-game/submissions/550696627/?envType=daily-question&envId=2024-07-29
//682. 棒球比赛
int calPoints(vector<string>& operations) {
    vector<int> res;
    for (auto ch : operations)
    {
        if (ch == "C")
            res.pop_back();
        else if (ch == "D")
            res.push_back(res.back() * 2);
        else if (ch == "+")
        {
            int last = res.back();
            res.pop_back();
            int tmp = last + res.back();
            res.push_back(last);
            res.push_back(tmp);
        }
        else
        {
            res.push_back(stoi(ch));
        }
    }
    // for(auto e : res)
    //     cout<< e<<" ";
    return accumulate(res.begin(), res.end(), 0);
}


//https://leetcode.cn/problems/double-modular-exponentiation/?envType=daily-question&envId=2024-07-30
// 2961. 双模幂运算
//[31,12,21,24]  过不去
bool is_goodidex(vector<int> nums, int& target)
{
    double a = nums[0]; double b = nums[1];
    double c = nums[2]; double m = nums[3];
    //cout << fmod(pow(fmod(pow(a, b), 10), c), m) <<endl;
    if (fmod(pow(fmod(pow(a, b), 10), c), m) == target) //这里有问题 或者写成 每一次pow(a, b) 相乘都%10
        return true;
    return false;
}

//快速幂  递归的思想 比如说求x^77 --> x^38 --> x^19 --> x^9 --> x^4 --> x^2 ---> x
//从右往左递推
int pow_mod(int x, int y, int mod) {
    int res = 1;
    while (y)
    {
        //2^5 --> 2^2 --> 2^1 -->2^0
        //2^4 --> 2^2 --> 2^1 -->2^0
        if (y & 1) //是奇数
        {
            res = res * x % mod;
        }
        //如果是偶次方
        res = res * x * x % mod;
        y >>= 1;
    }
    return res;
}
vector<int> getGoodIndices(vector<vector<int>>& variables, int target)
{
    vector<int> res;
    for (int i = 0; i < variables.size(); ++i)
    {
        auto& v = variables[i];
        if (pow_mod(pow_mod(v[0], v[1], 10), v[2], v[3]) == target)
        {
            res.push_back(i);
        }
    }
    return res;
}


//https://leetcode.cn/problems/minimum-rectangles-to-cover-points/?envType=daily-question&envId=2024-07-31
//3111. 覆盖所有点的最少矩形数目
int minRectanglesToCoverPoints(vector<vector<int>>& points, int w) {
    sort(points.begin(), points.end());
    int cnt = 0;
    for (int i = 0; i < points.size(); )
    {
        auto& pos = points[i];
        int wide = w + pos[0];
        while (pos[0] <= wide)
        {
            i++;
            if (i >= points.size())
                break;
            pos = points[i];
        }
        cnt++;

    }
    return cnt;
}


//https://leetcode.cn/problems/uOAnQW/?envType=daily-question&envId=2024-08-01
//LCP 40. 心算挑战
int maxmiumScore(vector<int>& cards, int cnt) {
    //sort(cards.begin(), cards.end(), greater<int>());
    sort(cards.begin(), cards.end(), [](int& e1, int& e2) {return e1 > e2; });

    //9 8 4 2 1 1 0  n=3
    //9 7 3 2 1 1 0
    //**判断最后n下表是 偶数还是奇数 4 3   如果是4就找后面最大的奇数 如果是3就找后面最大的偶数 好像不行**/
    //如果是sum是奇数 找后面最大的奇数和最小的偶数替换
    //          或者 找后面最大的偶数和最小的奇数替换
    //int sum = accumulate(cards.begin(), cards.begin()+cnt, 0);
    //if(sum % 2 == 0)
        //return sum;

    //找出sum中最小的偶数 最小的奇数
    int min_even = -1;
    int min_odd = -1;
    int temp = 0;
    for (int i = 0; i < cnt; ++i)
    {
        temp += cards[i];
        if (cards[i] & 1 != 0)       //还有一种方法来判别 是否是偶数 cards[i] % 2 == 0
            min_even = cards[i];
        else
            min_odd = cards[i];
    }
    if (temp % 2 == 0)
        return temp;

    int sum = 0;
    for (int i = cnt; i < cards.size(); ++i)
    {
        if (cards[i] & 1 != 0)
        {
            if (min_odd != -1) //说明之前的temp里有奇数
                sum = max(sum, temp - min_odd + cards[i]);
        }
        else
        {
            if (min_even != -1)
                sum = max(sum, temp - min_even + cards[i]);
        }
        // //判断最后一个数是 奇数还是偶数
        // if(cards[cnt-1] % 2 == 0)
        // {
        //     if(cards[i] % 2 != 0)
        //         return sum - cards[cnt-1] + cards[i];
        // }
        // else{
        //     if(cards[i] % 2 == 0)
        //         return sum - cards[cnt-1] + cards[i];                    
        // }

    }
    return sum;
}


//https://leetcode.cn/problems/right-triangles/?envType=daily-question&envId=2024-08-02
//3128. 直角三角形
long long numberOfRightTriangles(vector<vector<int>>& grid)
{
    int m = grid.size();
    int n = grid[0].size();
    vector<int> rows(m);
    vector<int> cols(n);
    for (int i = 0; i < m; ++i)
    {
        for (int j = 0; j < n; ++j)
        {
            rows[i] += grid[i][j];
            cols[j] += grid[i][j];
        }
    }

    long long res = 0;
    for (int i = 0; i < m; ++i)
    {
        for (int j = 0; j < n; ++j)
        {
            if (grid[i][j] == 1) {
                res += (rows[i] - 1) * (cols[j] - 1);
            }
        }
    }

    return res;
}



//https://leetcode.cn/problems/subtree-of-another-tree/?envType=daily-question&envId=2024-08-04
//572. 另一棵树的子树
bool isSameTree(TreeNode* root, TreeNode* subRoot)
{
    //如果判断到最后 都是 空 说明是字串
    if (root == nullptr && subRoot == nullptr)
        return true;

    if (root == nullptr || subRoot == nullptr)
        return false;

    if (root->val != subRoot->val)
        return false;

    return isSameTree(root->left, subRoot->left) && isSameTree(root->right, subRoot->right);
}

bool isSubtree(TreeNode* root, TreeNode* subRoot) {
    if (root == nullptr)
        return false;
    if (isSameTree(root, subRoot))
        return true;

    return isSubtree(root->left, subRoot) || isSubtree(root->right, subRoot);
}



//https://leetcode.cn/problems/maximum-points-inside-the-square/?envType=daily-question&envId=2024-08-03
//3143. 正方形中的最多点数
int MinRaduis(int x, int y)
{
    return max(abs(x), abs(y));
}

int maxPointsInsideSquare(vector<vector<int>>& points, string s)
{
    //每个字母都维护一个自己的最短路径 知道遇到相同
    //unordered_map<char, int> hash;
    vector<int> hash(26, INT_MAX);

    int n = points.size();
    int level = INT_MAX;
    for (int i = 0; i < n; ++i)
    {
        auto& x = points[i][0];
        auto& y = points[i][1];
        int ch = s[i] - 'a';

        int d = MinRaduis(x, y);
        if (d < hash[ch])
        {
            level = min(level, hash[ch]);
            hash[ch] = d;
        }
        else if (d < level)
        {
            level = d;
        }


        // if(hash.count(ch) == 0)
        // {
        //     //没有元素
        //     hash[ch] = MinRaduis(x, y);
        // }
        // else
        // {
        //     level = min({MinRaduis(x, y), hash[ch], level});
        //     break;
        // }
    }

    int cnt = 0;
    for (auto& ch : hash)
    {
        if (ch < level)
            cnt++;
    }
    return cnt;


}


//https://leetcode.cn/problems/rotate-list/?envType=study-plan-v2&envId=top-interview-150
//61. 旋转链表
ListNode* rotateRight(ListNode* head, int k)
{
    if (!head)
        return nullptr;
    //变成环
    int n = 0;
    ListNode* phead = new ListNode(-1, head);
    ListNode* prev = phead;
    ListNode* cur = head;
    while (cur)
    {
        n++;
        prev = cur;
        cur = cur->next;
    }
    //改成环
    prev->next = phead->next;

    //逆时针找K次 就是顺时针找 n-k 次
    k %= n;
    int cnt = n - k;

    prev = phead;
    cur = head;
    while (cnt--)
    {
        prev = cur;
        cur = cur->next;
    }
    prev->next = nullptr;
    delete phead;
    return cur;

}


//1019. 链表中的下一个更大节点
//https://leetcode.cn/problems/next-greater-node-in-linked-list/
vector<int> nextLargerNodes(ListNode* head)
{
    ListNode* cur = head;
    vector<int> ret;
    //需要先给 ret 开辟一个空间
    while (cur)
    {
        ret.push_back(0);
        cur = cur->next;
    }

    cur = head;
    stack<pair<int, int>> st; //一个放值 一个下标吗
    //设置一个下标 index
    int index = 0;
    //2 1 6 7 5 6 4 3 5 
    while (cur)
    {
        while (!st.empty() && st.top().first < cur->val)
        {
            //维护单调递减栈 将栈 退出为空
            ret[st.top().second] = cur->val;
            st.pop();
        }

        //入栈
        st.push({ cur->val, index });
        cur = cur->next;
        index++;
    }
    return ret;

}

//https://leetcode.cn/problems/find-the-integer-added-to-array-i/?envType=daily-question&envId=2024-08-08
//3131. 找出与数组相加的整数 I
int addedInteger(vector<int>& nums1, vector<int>& nums2)
{
    return *min_element(nums2.begin(), nums2.end()) - *min_element(nums1.begin(), nums1.end());

}


//https://leetcode.cn/problems/find-the-integer-added-to-array-ii/?envType=daily-question&envId=2024-08-09
//3132. 找出与数组相加的整数 II
//https://leetcode.cn/problems/is-subsequence/submissions/524199592/
//判断子序列
int minimumAddedInteger(vector<int>& nums1, vector<int>& nums2)
{
    sort(nums1.begin(), nums1.end());
    sort(nums2.begin(), nums2.end());

    //4   8   12   16   20
    //10  14  18
    //nums1要删除两个 如果留下的是最大的 比如说20
    //那么说明 nums1全体-10 看nums2是不是nums1的子序列  是不可能的有的
    //所以留下的数至少得从倒着 nums2.size() 相等的位置开始算 比如 12 开始
    //也就是 实际是从下标为 2开始向前算
    for (int i = 2; i >= 0; --i)
    {
        int x = nums2[0] - nums1[i];
        //在 nums1[i]+x 中找为nums2的子序列
        //双指针
        for (int k = i, j = 0; k < nums1.size(); ++k)
        {
            if (nums1[k] + x == nums2[j])
            {
                //可以直接返回  题目保证一定有答案的
                ++j;
                if (j >= nums2.size())
                    return x;
            }
        }
    }
    return 0;

}


//https://leetcode.cn/problems/isomorphic-strings/?envType=study-plan-v2&envId=top-interview-150
//205. 同构字符串
bool isIsomorphic(string s, string t)
{
    if (s.size() != t.size())
        return false;
    unordered_map<char, char> hashs;
    unordered_map<char, char> hasht;

    int len = s.size();
    for (int i = 0; i < len; ++i)
    {
        //两边一起走
        int x = s[i]; int y = t[i];

        //每一次都要检查一下是否都是一一对应
        if ((hashs.count(x) && hashs[x] != y) || (hasht.count(y) && hasht[y] != x))
        {
            return false;
        }
        hashs[s[i]] = t[i];
        hasht[t[i]] = s[i];
    }
    return true;
}


//https://leetcode.cn/problems/sort-colors/
//75. 颜色分类
void sortColors(vector<int>& nums)
{
    //用三指针来划分数组区域 化成三部分 实际是有四部分
    //[0, left]  [left+1, i-1]  [i, right-1]  [right, n-1]
    // 0             1           未扫描元素         2
    int n = nums.size();
    //由上可知 i == right的时候 全部都已经排序完成
    for (int i = 0, left = 0, right = n - 1; i <= right; )
    {
        if (nums[i] == 0)
        {
            swap(nums[left], nums[i]);
            left++;
            i++;
        }
        else if (nums[i] == 2) {
            swap(nums[right], nums[i]);
            right--;
        }
        else
        {
            i++;
        }
    }
}


//https://leetcode.cn/problems/valid-anagram/
//242. 有效的字母异位词
bool isAnagram(string s, string t) {
    if (s.size() != t.size())
        return false;

    sort(s.begin(), s.end());
    sort(t.begin(), t.end());
    for (int i = 0; i < s.size(); ++i)
    {
        if (s[i] != t[i])
            return false;
    }
    return true;
}


//https://leetcode.cn/problems/special-array-i/?envType=daily-question&envId=2024-08-13
//3151. 特殊数组 I
bool isArraySpecial(vector<int>& nums) {
    for (int i = 1; i < nums.size(); ++i)
    {
        if (nums[i] % 2 == nums[i - 1] % 2)
            return false;
    }
    return true;
}


//3152. 特殊数组 II
//https://leetcode.cn/problems/special-array-ii/?envType=daily-question&envId=2024-08-14
vector<bool> isArraySpecial(vector<int>& nums, vector<vector<int>>& queries)
{
    vector<bool> res;
    int n = nums.size();

    vector<int> dp(n, 1);
    // 4 3 1 6
    // 1 2 1 2  dp值
    for (int i = 1; i < n; ++i)
    {
        //如果相邻是奇偶数
        //或者用位运算来判断奇偶数
        //if((nums[i] % 2) != (nums[i-1] % 2))
        if ((nums[i] ^ nums[i - 1]) & 1 == 1)
        {
            dp[i] = dp[i - 1] + 1;
        }
    }

    // 3 4 1 2 6 5 4 8
    // 1 2 3 4 1 2 3 1 dp值  [4,6]
    for (auto& elem : queries)
    {
        int x = elem[0];
        int y = elem[1];
        if (y - x + 1 <= dp[y])
            res.push_back(true);
        else
            res.push_back(false);
    }
    return res;
}



//https://leetcode.cn/problems/sort-an-array/solutions/178305/pai-xu-shu-zu-by-leetcode-solution/
//912. 排序数组
int rand_index(int left, int right)
{
    return (rand() % (right - left) + 1) + left;
}

void Quick_Sort(vector<int>& nums, int l, int r)
{
    if (l >= r)
        return;

    //随机选取 key 值  返回下标
    int rand_i = rand_index(l, r);
    int key = nums[rand_i];

    //数组划分三块区域
    //[l, left] [left+1, i-1] [i, right-1] [right, r]
    int i = l, left = l - 1, right = r + 1;  //r + 1 !!注意捏
    while (i < right)
    {
        if (nums[i] < key)
        {
            swap(nums[++left], nums[i]);
            ++i;
        }
        else if (nums[i] == key)
        {
            ++i;
        }
        else
        {
            swap(nums[--right], nums[i]);
        }
        //换完后 [l, left] [left+1, right-1] [right ,r]

        Quick_Sort(nums, l, left);
        Quick_Sort(nums, right, r);
    }
}

vector<int> sortArray(vector<int>& nums)
{
    //快排 数组划分成三个区域 + 随机选key
    srand(time(NULL));
    Quick_Sort(nums, 0, nums.size() - 1);
    return nums;

}


//https://leetcode.cn/problems/minimum-number-of-operations-to-make-word-k-periodic/?envType=daily-question&envId=2024-08-17
//3137. K 周期字符串需要的最少操作次数
int minimumOperationsToMakeKPeriodic(string word, int k) {
    //字串的长度只能是为 k 能被 n 整除
    //所以其实就是找出 最大重复子串的个数(len = k) 最少操作数
    int n = word.size();
    unordered_map<string, int> count;
    for (int i = 0; i < n; i += k)
    {
        //可以 左值直接这样写
        string part = word.substr(i, k);
        count[part]++;
    }

    //只需要找出hash表中最大值即可
    //le:2   et:2  co : 1
    int ret = INT_MIN;
    for (auto& iter : count)
    {
        ret = max(ret, iter.second);
    }

    return n / k - ret;
}
// 或者 用右值引用 C++11
int minimumOperationsToMakeKPeriodic(string word, int k) {
    //字串的长度只能是为 k 能被 n 整除
    //所以其实就是找出 最大重复子串的个数(len = k) 最少操作数
    int n = word.size();
    unordered_map<string, int> count;
    int ret = INT_MIN;

    for (int i = 0; i < n; i += k)
    {
        //可以 左值直接这样写 但是如果字符串大 临时对象拷贝消耗会很大
        //string part = word.substr(i, k);

        //所以可以使用右值引用  引用这个临时对象 直接移到count里
        //string &part = word.substr(i, k);   会报错 不能引用 右值
        string&& part = word.substr(i, k);
        count[part]++;
        ret = max(ret, count[part]);
    }

    //只需要找出hash表中最大值即可
    //le:2   et:2  co : 1
    return n / k - ret;
}



bool checkRecord(string s)
{
    int cnt_A = 0, cnt_L = 0;
    for (auto& ch : s)
    {
        if (ch == 'A')
            cnt_A++;
        if (ch == 'L')
            cnt_L++;
        else
            cnt_L = 0;
        if (cnt_A >= 2 || cnt_L >= 3)
            return false;
    }
    return true;


}


//https://leetcode.cn/problems/kth-largest-element-in-an-array/solutions/307351/shu-zu-zhong-de-di-kge-zui-da-yuan-su-by-leetcode-/
//215. 数组中的第K个最大元素
class Solution {
public:
    int GetRandon(vector<int>& nums, int left, int right)
    {
        return nums[(rand() % (right - left) + 1) + left];
    }
    int QSort(vector<int>& nums, int l, int r, int k)
    {
        //这里等于的时候 返回数组元素 已经没元素了
        if (l == r)
        {
            return nums[l];
        }
        //获取随机 key 值
        int key = GetRandon(nums, l, r);

        //三路划分
        int i = l, left = l - 1, right = r + 1;
        while (i < right)
        {
            if (nums[i] < key) {
                swap(nums[i++], nums[++left]);
            }
            else if (nums[i] == key) {
                i++;
            }
            else {
                swap(nums[i], nums[--right]);
            }
        }

        //关键！ 确定每段区间的个数
        //  <key          =key           >key
        //[l, left] [left+1, right-1] [right, r]
        //    a             b             c
        int c = r - right + 1;
        int b = right - 1 - left;
        if (c >= k)
        {
            return QSort(nums, right, r, k);
        }
        else if (b + c >= k)
        {
            return key;
        }
        else
        {
            //找的是最左边这段区间的 第 k - b -c大的值
            return QSort(nums, l, left, k - b - c);
        }
    }

    int findKthLargest(vector<int>& nums, int k)
    {
        srand(time(NULL));
        // 使用快速选择算法 基于快排 看看笔记吧
        return QSort(nums, 0, nums.size() - 1, k);
    }
};

//https://leetcode.cn/problems/smallest-k-lcci/
//面试题 17.14. 最小K个数
class Solution {
public:
    //1.直接qsort排序
    //2.大堆维护
    //3.快速选择算法
    int GetRand(vector<int>& nums, int left, int right)
    {
        return nums[(rand() % (right - left) + 1) + left];
    }
    void QSort(vector<int>& nums, int l, int r, int k)
    {
        if (l >= r)
            return;

        int key = GetRand(nums, l, r);

        int i = l, left = l - 1, right = r + 1;
        while (i < right)
        {
            if (nums[i] < key) {
                swap(nums[i++], nums[++left]);
            }
            else if (nums[i] == key) {
                ++i;
            }
            else
            {
                swap(nums[i], nums[--right]);
            }
        }

        //数组被划分成了三块
        //[l, left] [left+1, right-1] [right, r]
        //个数 a            b              c 

        int a = left - l + 1;
        int b = right - 1 - left;
        if (a >= k)
        {
            QSort(nums, l, left, k);
        }
        else if (a + b >= k)
        {
            return;
        }
        else
        {
            return QSort(nums, right, r, k - a - b);
        }
    }
    vector<int> smallestK(vector<int>& arr, int k) {
        srand(time(NULL));
        QSort(arr, 0, arr.size() - 1, k);
        return { arr.begin(), arr.begin() + k };
    }
};


//https://leetcode.cn/problems/sort-an-array/
//912. 排序数组  ---归并算法
vector<int> tmp;
void mergesort(vector<int>& nums, int left, int right)
{
    if (left >= right)
        return;

    //1.取出一个中间值
    //int mid = left + ((right - left) >> 1); //这里写错了 优先级 >> 没有加括号 left + (right - left) >> 1
    int mid = left + (right - left) / 2;
    //[left, mid] [mid+1, right]

    //2.归并 归操作
    mergesort(nums, left, mid);
    mergesort(nums, mid + 1, right);

    //3.对两个有序数组 进行排序
    // 先是两个数 再是 四个数 一直往上 合并
    //vector<int> tmp(right - left + 1);
    int cur1 = left, cur2 = mid + 1, i = 0;
    while (cur1 <= mid && cur2 <= right)
    {
        //可以这样写成一行 两个有序数组合并
        tmp[i++] = nums[cur1] <= nums[cur2] ? nums[cur1++] : nums[cur2++];
    }
    //判断是否有一个是走完了
    while (cur1 <= mid)
    {
        tmp[i++] = nums[cur1++];
    }
    while (cur2 <= right)
    {
        tmp[i++] = nums[cur2++];
    }

    //重新改写到 nums 里  还原
    for (int i = left; i <= right; ++i)
    {
        nums[i] = tmp[i - left];
    }
}

vector<int> sortArray(vector<int>& nums)
{
    tmp.resize(nums.size());
    mergesort(nums, 0, nums.size() - 1);
    //其实类似于 二叉树的后序遍历  而快排类似于前序遍历
    return nums;
}


//3146. 两个字符串的排列差
//https://leetcode.cn/problems/permutation-difference-between-two-strings/?envType=daily-question&envId=2024-08-22
int findPermutationDifference(string s, string t)
{
    unordered_map<char, int> maps;
    unordered_map<char, int> mapt;
    for (int i = 0; i < s.size(); ++i)
    {
        maps[s[i]] = i;
        mapt[t[i]] = i;
    }
    int ret = 0;
    for (auto& elem : s)
    {
        //cout << elem <<" ";
        auto& ti = mapt[elem];
        auto& si = maps[elem];
        ret += abs(ti - si);
    }
    return ret;
}

//709. 转换成小写字母
//https://leetcode.cn/problems/to-lower-case/
string toLowerCase(string s) {
    for (int i = 0; i < s.size(); ++i)
    {
        s[i] = tolower(s[i]);
    }
    return s;

}


//https://leetcode.cn/problems/shu-zu-zhong-de-ni-xu-dui-lcof/
//LCR 170. 交易逆序对的总数
class Solution {
public:
    vector<int> tmp;
    int cnt = 0;
public:
    void mergesort(vector<int>& nums, int left, int right)
    {
        if (left >= right)
            return;

        //取出一个中间值
        int mid = left + (right - left) / 2;
        //[left, mid] [mid+1, right]

        //归并 后序遍历
        mergesort(nums, left, mid);
        mergesort(nums, mid + 1, right);

        int cur1 = left, cur2 = mid + 1;
        int i = 0;

        //策略1 对数组排升序，那么就需要找到 再该数之前有多少个比我大的数
        // while(cur1 <= mid && cur2 <= right)
        // {
        //     if(nums[cur1] > nums[cur2])
        //     {
        //         tmp[i] = nums[cur2];
        //         cnt += mid - cur1 + 1;
        //         cur2++;
        //     }
        //     else
        //     {
        //         tmp[i] = nums[cur1];
        //         cur1++;
        //     }
        //     i++;
        // }

        //策略2 如果排序排的是 降序 ，那么就要找出的是该数之后有多少个比我大的数
        while (cur1 <= mid && cur2 <= right)
        {
            if (nums[cur1] > nums[cur2]) //注意是 >
            {
                tmp[i++] = nums[cur1++];
                cnt += right - cur2 + 1;
            }
            else
            {
                tmp[i++] = nums[cur2++];
            }
        }

        //这里还要判断一下 是哪一个数组走完了
        while (cur1 <= mid)
            tmp[i++] = nums[cur1++];
        while (cur2 <= right)
            tmp[i++] = nums[cur2++];

        //还原到原数组
        for (int i = left; i <= right; ++i)
            nums[i] = tmp[i - left];

    }
    int reversePairs(vector<int>& record)
    {
        tmp.resize(record.size());
        cnt = 0;
        mergesort(record, 0, record.size() - 1);
        return cnt;
    }

    // int reversePairs(vector<int>& record) 
    // {
    //     int cnt = 0;
    //     for(int i = 0; i < record.size(); ++i)
    //     {
    //         for(int j = i+1; j < record.size(); ++j)
    //         {
    //             if(record[i] > record[j])
    //                 cnt++;
    //         }
    //     }
    //     return cnt;
    // }
};

//https://leetcode.cn/problems/check-if-grid-satisfies-conditions/?envType=daily-question&envId=2024-08-29
//3142. 判断矩阵是否满足条件
bool satisfiesConditions(vector<vector<int>>& grid)
{
    int m = grid.size();
    int n = grid[0].size();
    for (int i = 0; i < m; ++i)
    {
        for (int j = 0; j < n; ++j)
        {
            if (j + 1 < m && i < n && grid[j][i] != grid[j + 1][i])
                return false;

            if (j + 1 < n && i < m && grid[i][j] == grid[i][j + 1])
                return false;
        }
    }
    return true;

}


//https://leetcode.cn/problems/sum-of-digit-differences-of-all-pairs/?envType=daily-question&envId=2024-08-30
//3153. 所有数对中数位差之和
long long sumDigitDifferences(vector<int>& nums)
{
    long long ret = 0;
    int n = nums.size();

    while (nums[0])
    {
        vector<int> cnt(10); //最大位数 0-9
        for (int i = 0; i < n; ++i)
        {
            cnt[nums[i] % 10]++;
            nums[i] /= 10;
        }
        //一次比最后一位有多少个不同
        for (int i = 0; i < 10; ++i)
        {
            ret += (long long)(n - cnt[i]) * cnt[i];
        }
    }
    return ret / 2;

    ////////////////////////////////////////////////////////////
    // int len = 0;
    // int k = nums[0];
    // while(k)
    // {
    //     k /= 10;
    //     len++;
    // }
    // long long ret = 0;
    // for(int i = 0; i < nums.size(); ++i)
    // {
    //     for(int j = i+1; j < nums.size(); ++j)
    //     {
    //         int n = len;
    //         int x = nums[i];
    //         int y = nums[j];
    //         while(n--)
    //         {
    //             //cout << "nums[i]:"<<nums[i] << " nums[j]:"<<nums[j];
    //             //cout << " nums[i]%10: "<< x % 10 << "  "<<"nums[j]%10: "<< y % 10 ;
    //             if(x % 10 != y % 10)
    //             {
    //                 //cout << " " << ret <<endl;
    //                 ret++;
    //             }
    //             x /= 10;
    //             y /= 10;
    //         }
    //     }
    // }
    // return ret;
    ////////////////////////////////////////////////////////////
}

//https://leetcode.cn/problems/make-a-square-with-the-same-color/?envType=daily-question&envId=2024-08-31
//3127. 构造相同颜色的正方形
bool canMakeSquare(vector<vector<char>>& grid)
{
    for (int i = 0; i < 2; ++i)
    {
        for (int j = 0; j < 2; ++j)
        {
            int wcnt = 0;
            int bcnt = 0;
            if (grid[i][j] == 'W')
                wcnt++;
            else
                bcnt++;

            if (grid[i][j + 1] == 'W')
                wcnt++;
            else
                bcnt++;

            if (grid[i + 1][j] == 'W')
                wcnt++;
            else
                bcnt++;

            if (grid[i + 1][j + 1] == 'W')
                wcnt++;
            else
                bcnt++;

            if (wcnt >= 3 || bcnt >= 3)
                return true;
        }
    }
    return false;
}

//https://leetcode.cn/problems/number-of-students-doing-homework-at-a-given-time/?envType=daily-question&envId=2024-09-01
//1450. 在既定时间做作业的学生人数
int busyStudent(vector<int>& startTime, vector<int>& endTime, int queryTime) {
    int cnt = 0;
    for (int i = 0; i < startTime.size(); ++i)
    {
        if (startTime[i] <= queryTime && endTime[i] >= queryTime)
            cnt++;
    }
    return cnt;
}


//315. 计算右侧小于当前元素的个数
//https://leetcode.cn/problems/count-of-smaller-numbers-after-self/
class Solution {
public:
    //LCR 170. 交易逆序对的总数 降序  第二个关键是要找出 nums 中当前元素的原始下标才可以

    vector<int> index; //记录 nums 中当前元素的原始下标

    vector<int> nums_tmp; //nums 的辅助数组
    vector<int> index_tmp; //index 的辅助数组

    vector<int> ret; //返回数组
public:
    void mergesort(vector<int>& nums, int left, int right)
    {
        if (left >= right)
            return;

        //根据中间元素划分区间
        int mid = left + (right - left) / 2;

        mergesort(nums, left, mid);
        mergesort(nums, mid + 1, right);

        //划分成两个数组 归并
        int cur1 = left, cur2 = mid + 1, i = 0;

        //降序排序 ，可以参考 LCR170
        while (cur1 <= mid && cur2 <= right)
        {
            if (nums[cur1] <= nums[cur2])
            {
                //先记录到 nums_tmp 数组
                nums_tmp[i] = nums[cur2];
                index_tmp[i] = index[cur2];
                cur2++;
                i++;
            }
            else
            {
                ret[index[cur1]] += right - cur2 + 1;
                nums_tmp[i] = nums[cur1];
                index_tmp[i] = index[cur1];
                i++;
                cur1++;
            }
        }

        while (cur1 <= mid)
        {
            nums_tmp[i] = nums[cur1];
            index_tmp[i++] = index[cur1++];
        }

        while (cur2 <= right)
        {
            nums_tmp[i] = nums[cur2];
            index_tmp[i++] = index[cur2++];
        }

        //还原
        //两个都要还原
        for (int i = left; i <= right; ++i)
        {
            nums[i] = nums_tmp[i - left];
            index[i] = index_tmp[i - left];
        }
    }

    vector<int> countSmaller(vector<int>& nums)
    {
        int n = nums.size();
        nums_tmp.resize(n);
        index.resize(n);
        index_tmp.resize(n);
        ret.resize(n);

        //index 数组先初始化 
        for (int i = 0; i < n; ++i)
        {
            index[i] = i;
        }

        mergesort(nums, 0, nums.size() - 1);
        return ret;
    }

};

//2860. 让所有学生保持开心的分组方法数
//https://leetcode.cn/problems/happy-students/?envType=daily-question&envId=2024-09-04
int countWays(vector<int>& nums) {
    int n = nums.size();
    sort(nums.begin(), nums.end());
    int ret = 0;

    for (int k = 0; k <= n; ++k)
    {
        if (k > 0 && nums[k - 1] >= k)
            continue;

        if (k < n && nums[k] <= k)
            continue;

        ret++;
    }
    return ret;


}

//https://leetcode.cn/problems/clear-digits/?envType=daily-question&envId=2024-09-05
//3174. 清除数字
string clearDigits(string s) {
    string ret;
    int n = s.size();
    for (int i = 0; i < n; ++i)
    {
        if (isdigit(s[i]))
        {
            ret.pop_back();
        }
        else
        {
            ret.push_back(s[i]);
        }
    }
    return ret;


}

//https://leetcode.cn/problems/add-two-numbers/description/
//. 两数相加
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2)
{
    ListNode* phead = new ListNode(-1, nullptr);
    ListNode* tail = phead; //需要一个尾指针来记录尾插

    ListNode* cur1 = l1;
    ListNode* cur2 = l2;

    int carry = 0;
    while (cur1 || cur2 || carry == 1) //有一个链表走完了也需要继续进行加法运算
    {
        int sum = 0;
        if (cur1)
        {
            sum += cur1->val;
            cur1 = cur1->next;
        }

        if (cur2)
        {
            sum += cur2->val;
            cur2 = cur2->next;
        }
        sum += carry;

        ListNode* tmp = new ListNode(sum % 10);
        tail->next = tmp;
        tail = tail->next;
        carry = sum / 10;
    }
    // if(carry == 1) //也可以放到上面循环里
    // {
    //     tail->next = new ListNode(1);
    // }

    ListNode* newhead = phead->next;

    delete phead;

    return newhead;

}

//https://leetcode.cn/problems/squares-of-a-sorted-array/?envType=daily-question&envId=2024-09-08
//977. 有序数组的平方
vector<int> sortedSquares(vector<int>& nums)
{
    vector<int> ret;
    for (int i = 0; i < nums.size(); ++i)
    {
        ret.push_back(nums[i] * nums[i]);
    }
    sort(ret.begin(), ret.end());

    return ret;
}


//https://leetcode.cn/problems/merge-nodes-in-between-zeros/?envType=daily-question&envId=2024-09-09
//2181. 合并零之间的节点
ListNode* mergeNodes(ListNode* head)
{
    ListNode* cur = head;
    ListNode* phead = new ListNode(-1, nullptr);
    ListNode* tail = phead;
    while (cur)
    {
        int sum = 0;
        while (cur && cur->val != 0)
        {
            sum += cur->val;
            cur = cur->next;
        }
        if (cur && cur->val == 0)
        {
            if (sum != 0)
            {
                ListNode* tmp = new ListNode(sum);
                tail->next = tmp;
                tail = tmp;
            }
            cur = cur->next;
        }

    }
    tail->next = nullptr;
    ListNode* newhead = phead->next;
    delete phead;

    return newhead;

}


//24. 两两交换链表中的节点
//https://leetcode.cn/problems/swap-nodes-in-pairs/
ListNode* swapPairs(ListNode* head)
{
    if (head == nullptr)
        return nullptr;

    ListNode* phead = new ListNode(-1, head);
    ListNode* prev = phead;
    ListNode* cur = head;
    ListNode* next = cur->next;

    while (cur && next)
    {
        ListNode* nnext = next->next;

        //交换两个节点
        prev->next = next;
        next->next = cur;
        cur->next = nnext;

        //向后移动  prev cur 等位置已经改变了
        prev = cur;
        cur = nnext;

        if (cur == nullptr)
            break;

        next = cur->next;
    }

    ListNode* newhead = phead->next;
    delete phead;
    return newhead;

}


//LCR 026. 重排链表
//https://leetcode.cn/problems/LGjMqU/
class Solution {
public:
    void reorderList(ListNode* head)
    {
        //或者在这里处理边界情况
        if (head == nullptr || head->next == nullptr || head->next->next == nullptr)
            return;

        // 1->2->3
        // 4->5   ----> 反转 5->4
        // 插入 1->5->2->4->3
        //1.先找出中心节点
        ListNode* slow = head;
        ListNode* fast = slow;
        ListNode* prev = slow;
        while (fast)
        {
            fast = fast->next;
            if (fast == nullptr)
                break;
            fast = fast->next;
            prev = slow;
            slow = slow->next;
        }

        //slow 就是中间节点
        ListNode* first_head = head;
        ListNode* second_head = slow;
        prev->next = nullptr;

        //此处调试已经完成了切割
        //2.反转后续链表2 头插
        ListNode* second_new_head = nullptr;
        ListNode* cur = second_head;
        ListNode* next = nullptr;
        while (cur)
        {
            next = cur->next;
            cur->next = second_new_head;
            second_new_head = cur;
            cur = next;
        }

        // cur = second_new_head;
        // while(cur)
        // {
        //     cout << cur->val << " ";
        //     cur = cur->next;
        // }

        //3.插入
        //先记录一下最开始的 head
        ListNode* guard = head;

        ListNode* cur1 = first_head;
        ListNode* cur2 = second_new_head;

        // if(cur1 == cur2)
        // {
        //     return;
        // }

        ListNode* phead = new ListNode(-1);
        ListNode* tail = phead;

        int flag = 1;
        while (cur1 && cur2)
        {
            if (flag == 1)
            {
                tail->next = cur1;
                tail = tail->next;
                cur1 = cur1->next;
                flag = 0;
            }
            else
            {
                tail->next = cur2;
                tail = tail->next;
                cur2 = cur2->next;
                flag = 1;
            }
        }
        if (cur1)
        {
            tail->next = cur1;
        }
        if (cur2)
        {
            tail->next = cur2;
        }

        delete phead;
    }

};

//https://leetcode.cn/problems/removing-stars-from-a-string/?envType=daily-question&envId=2024-09-14
//2390. 从字符串中移除星号

string removeStars(string s)
{
    string ret;
    for (char ch : s)
    {
        if (ch == '*')
        {
            ret.pop_back();
        }
        else
        {
            ret += ch;
        }
    }
    return ret;
}


//https://leetcode.cn/problems/points-that-intersect-with-cars/?envType=daily-question&envId=2024-09-15
//2848. 与车相交的点
int numberOfPoints(vector<vector<int>>& nums)
{
    sort(nums.begin(), nums.end());
    int sum = 0;
    int last_x = nums[0][0];
    int last_y = nums[0][1];
    sum += (last_y - last_x + 1);
    for (int i = 1; i < nums.size(); ++i)
    {
        int x = nums[i][0];
        int y = nums[i][1];

        if (y < last_y)
        {
            last_x = max(x, last_x);
            last_y = max(y, last_y);
            continue;
        }

        //说明 y > last_y 接下来判断 x
        if (x > last_y)
        {
            sum += (y - x + 1);
        }
        else
        {
            sum += (y - last_y);
        }
        last_x = max(x, last_x);
        last_y = max(y, last_y);
    }
    return sum;
}

//https://leetcode.cn/problems/reverse-bits/
//190. 颠倒二进制位
uint32_t reverseBits(uint32_t n)
{
    uint32_t ret = 0;
    for (int i = 0; i < 32 && n > 0; ++i)
    {
        ret |= (n & 1) << (31 - i);
        n >>= 1;
    }
    return ret;
}


///https://leetcode.cn/problems/merge-k-sorted-lists/
//23. 合并 K 个升序链表
class Solution {
public:
    struct cmp
    {
        const bool operator()(const ListNode* l1, const ListNode* l2)
        {
            return l1->val > l2->val;
        }
    };
    ListNode* mergeKLists(vector<ListNode*>& lists)
    {
        //优先级队列 创建一个小根堆
        priority_queue<ListNode*, vector<ListNode*>, cmp> heap;

        //将所有的链表的头节点放入到 小根堆中   一次放 k 个 合并链表后再加入后续节点
        for (auto lt : lists)
        {
            if (lt)
                heap.push(lt);
        }

        //合并k个有序链表
        ListNode* phead = new ListNode(0);
        ListNode* tail = phead;

        while (!heap.empty())
        {
            ListNode* tmp = heap.top();
            heap.pop();
            tail->next = tmp;
            tail = tmp;

            //是将每一个节点放到堆里 以此来模仿 指针一直向后走
            if (tmp->next)
                heap.push(tmp->next);
        }

        ListNode* newhead = phead->next;
        delete phead;

        return newhead;
    }


};

//https://leetcode.cn/problems/zuo-xuan-zhuan-zi-fu-chuan-lcof/description/
//LCR 182. 动态口令
string dynamicPassword(string password, int target)
{
    string cutstr = password.substr(0, target);
    password += cutstr;
    return password.substr(target);

}

//https://leetcode.cn/problems/time-needed-to-buy-tickets/?envType=daily-question&envId=2024-09-29
//073. 买票需要的时间
int timeRequiredToBuy(vector<int>& tickets, int k)
{
    int n = tickets.size();
    int ret = 0;
    for (int i = 0; i < n; ++i)
    {
        //计算每个人所需要的时间
        if (i <= k)
        {
            ret += min(tickets[i], tickets[k]);
        }
        else
        {
            ret += min(tickets[i], tickets[k] - 1);
        }
    }
    return ret;

}


//1845. 座位预约管理系统
//https://leetcode.cn/problems/seat-reservation-manager/?envType=daily-question&envId=2024-09-30
class SeatManager {
private:
    //建立一个小根堆
    // 和 vector 相反?  greater 和 less
    priority_queue<int, vector<int>, greater<int>> q;
public:
    SeatManager(int n)
    {
        for (int i = 1; i <= n; ++i)
        {
            q.push(i);
        }
    }

    int reserve() {
        int top = q.top();
        q.pop();
        return top;
    }

    void unreserve(int seatNumber) {
        q.push(seatNumber);
    }
};


//面试题 02.01. 移除重复节点
//https://leetcode.cn/problems/remove-duplicate-node-lcci/description/
class Solution {
public:
    ListNode* removeDuplicateNodes(ListNode* head) {
        if (head == nullptr) {
            return head;
        }
        unordered_set<int> occurred = { head->val };
        ListNode* pos = head;
        // 枚举前驱节点
        while (pos->next != nullptr) {
            // 当前待删除节点
            ListNode* cur = pos->next;
            if (!occurred.count(cur->val)) {
                occurred.insert(cur->val);
                pos = pos->next;
            }
            else {
                pos->next = pos->next->next;
            }
        }
        pos->next = nullptr;
        return head;

    }

    //1227. 飞机座位分配概率
    //https://leetcode.cn/problems/airplane-seat-assignment-probability/?envType=daily-question&envId=2024-10-04
    double nthPersonGetsNthSeat(int n) {
        return n == 1 ? 1.0 : 0.5;

    }


    //3162. 优质数对的总数 I
    //https://leetcode.cn/problems/find-the-number-of-good-pairs-i/?envType=daily-question&envId=2024-10-10
    int numberOfPairs(vector<int>& nums1, vector<int>& nums2, int k) {
        int n = nums1.size();
        int m = nums2.size();

        int ret = 0;
        for (int a : nums1)
        {
            for (int b : nums2)
            {
                if (a % (b * k) == 0)
                {
                    ret++;
                }
            }
        }
        return ret;
    }

    //https://leetcode.cn/problems/jump-game/
    //55. 跳跃游戏
    bool canJump(vector<int>& nums) {
        int n = nums.size();
        int maxright = nums[0]; //最大能到的位置
        for (int i = 0; i < n; ++i)
        {
            //判断当前i能到达的最远的位置
            if (maxright >= i)
            {
                //判断是否超过当前下标 取大值
                maxright = max(maxright, i + nums[i]);
            }
            if (maxright >= n - 1)
                return true;

        }
        return false;
    }


    //https://leetcode.cn/problems/swap-numbers-lcci/
    //面试题 16.01. 交换数字
    vector<int> swapNumbers(vector<int>& numbers) {
        int& a = numbers[0];
        int& b = numbers[1];

        a = a ^ b;
        b = b ^ a;
        a = a ^ b;

        return numbers;

    }

https://job.yanmade.com/yanmaderecruit/phone/applyInfo


    //3194. 最小元素和最大元素的最小平均值
    //https://leetcode.cn/problems/minimum-average-of-smallest-and-largest-elements/?envType=daily-question&envId=2024-10-16
double minimumAverage(vector<int>& nums) {
    priority_queue<float, vector<float>, greater<float>> q;
    sort(nums.begin(), nums.end());
    int left = 0, right = nums.size() - 1;

    while (left < right)
        q.push((nums[left++] + nums[right--]) / 2.0);

    return q.top();
}

//https://leetcode.cn/problems/count-pairs-that-form-a-complete-day-i/description/
//3184. 构成整天的下标对数目 I
int countCompleteDayPairs(vector<int>& hours) {
    int n = hours.size();
    int ret = 0;
    for (int i = 0; i < n; ++i)
    {
        for (int j = i + 1; j < n; ++j)
        {
            if ((hours[i] + hours[j]) % 24 == 0)
                ret++;
        }
    }
    return ret;
}


int calculateDepth(TreeNode* root) {
    if (root == nullptr)
        return 0;
    return max(calculateDepth(root->left), calculateDepth(root->right)) + 1;

}

//https://leetcode.cn/problems/lexicographically-smallest-string-after-a-swap/?envType=daily-question&envId=2024-10-30
//3216. 交换后字典序最小的字符串
string getSmallestString(string s)
{
    int n = s.size();
    for (int i = 0; i + 1 < s.size(); i++)
    {
        if (s[i] > s[i + 1] && s[i] % 2 == s[i + 1] % 2)
        {
            swap(s[i], s[i + 1]);
            break;
        }
    }
    return s;
}


//https://leetcode.cn/problems/pascals-triangle-ii/submissions/577258990/
//119. 杨辉三角 II
vector<int> getRow(int rowIndex)
{
    vector<vector<int>> vv(rowIndex + 1);

    for (int i = 0; i <= rowIndex; ++i)
    {
        vv[i].resize(i + 1);
        vv[i][0] = vv[i][i] = 1;
        for (int j = 0; j < vv[i].size(); ++j)
        {
            if (vv[i][j] == 0)
                vv[i][j] = vv[i - 1][j - 1] + vv[i - 1][j];
        }

    }
    return vv[rowIndex];
}

// 定位new 的一些测试代码
class MyClass {
public:
    MyClass() {
        cout << "MyClass: 构造" << endl;
    }
    ~MyClass() {
        cout << "MyClass: 析构" << endl;
    }
    void print() {
        cout << "print " << endl;
    }
};

int main() {
    int* ptr = (int*)0x1234;
    cout << "address: " << ptr << endl;
    ptr = (int*)new (ptr)MyClass;
    cout << "address: " << ptr << endl;
    ((MyClass*)ptr)->print();
    //delete ptr;直接使用delete释放内存会报错
    ((MyClass*)ptr)->~MyClass();//必须显示调用析构函数来清理对象


}

//3226. 使两个整数相等的位更改次数
//https://leetcode.cn/problems/number-of-bit-changes-to-make-two-integers-equal/?envType=daily-question&envId=2024-11-02
int minChanges(int n, int k) {
    int cnt1 = 0;
    int cnt2 = 0;
    int num = n & k;
    if (num != k)
        return -1;

    while (n)
    {
        n &= n - 1;
        cnt1++;
    }
    while (k)
    {
        k &= k - 1;
        cnt2++;
    }
    return cnt1 - cnt2;

}

//3222. 求出硬币游戏的赢家
//https://leetcode.cn/problems/find-the-winning-player-in-coin-game/?envType=daily-question&envId=2024-11-05
string losingPlayer(int x, int y) {
    int ops = min(x, y / 4);
    return ops % 2 == 1 ? "Alice" : "Bob";

}


//https://leetcode.cn/problems/longest-palindromic-substring/
//5. 最长回文子串
class Solution {
public:
    string longestPalindrome(string s)
    {
        int n = s.size();
        vector<vector<int>> dp(n, vector<int>(n));

        int maxlen = 1;
        int begin = 0;

        for (int i = 0; i < n; ++i)
        {
            dp[i][i] = true;
        }

        for (int L = 2; L <= n; ++L)
        {
            for (int i = 0; i < n; ++i)
            {
                int j = i + L - 1;

                if (j >= n)
                {
                    break;
                }

                if (s[i] != s[j])
                {
                    dp[i][j] = false;
                }
                else
                {
                    if (j - i < 3)
                    {
                        dp[i][j] = true;
                    }
                    else
                    {
                        dp[i][j] = dp[i + 1][j - 1];
                    }
                }

                if (j - i + 1 > maxlen && dp[i][j])
                {
                    maxlen = j - i + 1;
                    begin = i;
                }

            }
        }

        return s.substr(begin, maxlen);
    }


};

//https://leetcode.cn/problems/snake-in-matrix/?envType=daily-question&envId=2024-11-21
//3248. 矩阵中的蛇
int finalPositionOfSnake(int n, vector<string>& commands) {
    int i = 0;
    int j = 0;

    for (const auto& str : commands)
    {
        if (str == "LEFT")
            --j;
        if (str == "RIGHT")
            ++j;
        if (str == "UP")
            --i;
        if (str == "DOWN")
            ++i;
    }
    return i * n + j;
}


//https://leetcode.cn/problems/alternating-groups-i/
//3206. 交替组 I
int numberOfAlternatingGroups(vector<int>& colors) {
    int n = colors.size();
    int ret = 0;
    for (int i = 0; i < n; ++i)
    {
        if (colors[i] != colors[(i + 1) % n] && colors[i] != colors[(i - 1 + n) % n])
        {
            ret++;
        }
    }
    return ret;
}

//https://leetcode.cn/problems/check-if-two-chessboard-squares-have-the-same-color/?envType=daily-question&envId=2024-12-03
//3274. 检查棋盘方格颜色是否相同
bool checkTwoChessboards(string coordinate1, string coordinate2) {
    // int x = abs(coordinate1[1] - coordinate2[1]);
    // int y = abs(coordinate1[0] - coordinate2[0]);

    // if(x % 2 == 0 && y % 2 == 0)
    // {
    //     return true;
    // }
    // return false;
    return (coordinate1[0] - coordinate2[0] + coordinate1[1] - coordinate2[1]) % 2 == 0;
}
